34 KiB
Piano di test: metadati di schema, campi sensibili e descrizioni AI
- Data: 2026-08-31
- Stato: proposto
- Baseline analizzata:
f586152sul branchtest/database-baseline
1. Obiettivo
Validare insieme le tre capacità recentemente introdotte in Database Management:
- acquisizione autorevole dei metadati fisici di uno schema esterno;
- proposta e revisione umana dei campi sensibili dal punto di vista privacy;
- generazione, revisione e consolidamento delle descrizioni di tabelle e colonne.
Il piano è risk-based: perdita o corruzione di metadati, lettura o invio di valori protetti e applicazione di una selezione al target sbagliato sono rischi bloccanti. La qualità linguistica dei testi AI è invece valutata separatamente dal contratto tecnico, perché l'output del modello è una proposta soggetta a revisione umana.
Questo documento non costituisce una certificazione normativa o GDPR: verifica i controlli tecnici e il flusso operativo implementati dal prodotto.
1.1 Assunzione operativa: ambiente completamente sacrificabile
Per indicazione esplicita del proprietario, l'installazione sul Mac è esclusivamente di sviluppo e test. Non contiene produzione e non esiste alcun requisito di conservazione dello stato locale.
catalog-db, migrazioni, configurazioni locali, run, eventi, flag, descrizioni curate e generate possono essere cancellati e ricreati tutte le volte necessarie;- il database reale già collegato è la fonte autorevole dalla quale ricostruire il catalogo ed è la sorgente primaria per validare schema, classificazione privacy e generazione delle descrizioni;
- reset completi, failure injection, dati incoerenti deliberati e prove distruttive sul catalogo locale sono ammessi senza backup o procedura di rollback dell'ambiente;
- compatibilità con stato locale preesistente, sessioni legacy e vecchie revisioni del catalogo non è un gate di questo piano;
- le prove di atomicità, idempotenza e preservazione dei campi restano necessarie perché verificano il comportamento del prodotto dentro un ciclo di test, non perché debbano proteggere il Mac.
Il database sorgente resta normalmente read-only: quando una prova richiede DDL o mutazioni fra scan e conferma si usa uno schema di test esplicitamente scrivibile o la fixture supplementare. La disponibilità a buttare lo stato locale non elimina il rischio di inviare dati personali a un provider esterno: proprio questa non-esfiltrazione è uno degli esiti principali da collaudare.
2. Terminologia e risultato atteso
I tre campi testuali del catalogo hanno autorità diverse e non devono essere confusi:
| Campo | Origine e autorità | Comportamento atteso |
|---|---|---|
sourceComment |
Commento fisico acquisito dalla sorgente | Si aggiorna con la sincronizzazione e non è modificabile come contenuto curato. |
generatedDescription |
Proposta prodotta dall'AI o corretta nel catalogo | È salvata separatamente, può essere rigenerata esplicitamente e non sovrascrive gli altri due campi. |
description |
Descrizione curata dall'amministratore | Cambia solo tramite modifica esplicita o consolidamento di una proposta selezionata. |
Nel seguito, “commento generato” indica generatedDescription. La generazione non deve mai
modificare sourceComment; il passaggio a description avviene solo con il consolidamento umano.
3. Riferimenti e baseline
Il comportamento da verificare deriva da:
- stato corrente del progetto in
PROJECT_STATE.md; - contratto Catalog Schema Snapshot;
- piano del Metadata Catalog;
- specifica della generazione descrizioni;
- ADR 0007: sincronizzazione autorevole durevole;
- ADR 0009: un solo run sequenziale di generazione;
- ADR 0010: campioni reali limitati;
- ADR 0011: Sensitive Data Flag;
- accettazione AI del 2026-08-29.
L'accettazione del 2026-08-29 è una baseline utile ma non chiude il gate attuale: precede i commit
0736983 e cb40c09, inviava campioni reali inventati e documentava che un valore campione era
stato ripreso nella descrizione. Deve quindi essere ripetuta sul comportamento privacy corrente.
4. Perimetro
Incluso
- trasporti
postgres_direct,rest_apiessh_tunnel; - RPC REST tipizzato
POST /rpc/schema_snapshote fallback singolo read-only suPOST /rpc/run_query; - metadati di tabelle, colonne, commenti sorgente, tipi, default, nullabilità, posizioni PK e coppie FK ordinate;
- scope di sincronizzazione
tables,columns,relationshipseall; - run durevoli, conferma delle differenze distruttive, cancellazione, recovery, eventi SSE e fallback polling;
- Sensitive Data Flag, analisi locale di metadati e contenuti, review draft e storico operativo;
- scope di generazione
selected_columns,selected_tables,allemissing; - campionamento read-only, valori sintetici per colonne protette, batching, retry, stop, Unlock, storico e consolidamento;
- uso controllato del database reale già collegato, inclusi schema e valori non sensibili, per il collaudo end-to-end con fake provider e provider configurati;
- permessi, minimizzazione dei dati, redazione di log/errori e resistenza a input ostili.
Escluso o rinviato
- applicazione del Sensitive Data Flag allo schema-linking/LSH del core, esplicitamente rinviata;
- sostituzione di
annotations.yaml, pubblicazione Qdrant e cutover del runtime NL→SQL; - alias, sinonimi, concetti, value descriptions e relazioni logiche;
- audit delle decisioni umane sul flag: per disegno si conserva solo il booleano corrente;
- DDL o scritture sul database sorgente;
- conservazione di cataloghi, run, descrizioni o sessioni locali precedenti al reset;
- compatibilità all'indietro con formati o migrazioni legacy non appartenenti alla baseline corrente.
5. Priorità e strategia
| Priorità | Significato | Esempi |
|---|---|---|
| P0 | Gate bloccante di sicurezza o integrità | Nessuna lettura/invio di valori protetti; applicazione atomica; scope esatto; segreti non esposti. |
| P1 | Contratto funzionale necessario al rilascio | Trasporti, stati dei run, recovery, batching, review e consolidamento. |
| P2 | Qualità, UX e robustezza non distruttiva | Copy, focus, benchmark del modello, carico e degrado SSE. |
Le prove sono distribuite su quattro livelli:
- Contratto/unità: repository in memoria, finti connector e Model Completer; nessuna rete.
- Integrazione: catalogo PostgreSQL ricreabile via Docker, database reale come sorgente, fixture supplementare, fake REST/SSH e Model Completer osservabile.
- UI/E2E locale: component test con MSW e almeno un flusso Playwright sullo stack locale.
- Accettazione L2: provider configurato realmente e database reale dopo review dei flag.
I test deterministici verificano il contratto. Le prove con un modello reale verificano compatibilità e qualità, ma non sostituiscono i gate P0.
6. Ambiente e dati di test
6.1 Ambiente minimo
- stack locale con
catalog-dbeliminabile, migrazioni ripetibili e backend/frontend della stessa baseline; - database reale già collegato come sorgente primaria, con utenza capace di
SELECTma non diINSERT,UPDATE,DELETE, DDL o cambio di schema; - PostgreSQL effimero supplementare solo per le mutazioni controllate che non devono essere fatte sul database reale;
- server REST fake in grado di servire snapshot valido, capability
unavailable, 404, risposta parziale/malformata e fallbackrun_query; - server OpenSSH effimero con
known_hostsesatto e varianti host key errata/assente; - Model Completer fake che registra transitoriamente i messaggi e restituisce esiti programmabili;
- browser senza segreti in Web Storage e raccolta di log backend/SSE/API per le scansioni canary.
Le prove PostgreSQL di integrazione non devono risultare skip: la disponibilità di Docker è una
precondizione del gate. Il catalogo locale può essere azzerato prima di ogni wave senza snapshot o
backup del suo stato precedente.
6.2 Database reale e fixture supplementare catalog_qa
La prima baseline viene acquisita dal database reale collegato. Il test registra soltanto inventario strutturale, conteggi e risultati sanitizzati; poi svuota il catalogo locale e dimostra di poterlo ricostruire dalla stessa sorgente. Non è richiesto preservare alcun metadato locale precedente.
La fixture catalog_qa integra il database reale soltanto quando servono casi controllabili o
mutazioni che la sorgente reale non contiene. Deve includere almeno:
customers: UUID PK, nome, email, codice fiscale, telefono, data di nascita, indirizzo e note;orders: FK versocustomers, importo numerico, stato, timestamp, default e campi nullable;order_lines: PK composta e relazione composta ordinata;clinical_events: campi sanitari evidenti e tabella partizionata;products: SKU pubblico, categoria, prezzo e flag booleano;empty_table: nessuna riga ma struttura valida;wide_entity: almeno 23 colonne e metadati lunghi, per forzare batch10 + 10 + 3e il limite dimensionale del messaggio;- identificatori quotati, commenti Unicode/italiani, commenti null e oggetti fuori dallo schema.
Usare valori canary inventati e univoci, per esempio:
PRIV_EMAIL_CANARY_...,PRIV_TAX_CANARY_...,PRIV_HEALTH_CANARY_...nelle colonne protette;PUBLIC_SKU_CANARY_...in una colonna esplicitamente non sensibile;SECRET_API_CANARY_...solo nel secret store del test.
I canary protetti non devono comparire nei messaggi al modello, nel catalogo, negli eventi, nelle API, nel DOM o nei log. Il canary pubblico può apparire nel messaggio al provider entro i limiti documentati e dopo la disclosure esplicita dell'utente. Sul database reale la stessa proprietà va provata soprattutto osservando la proiezione SQL e il payload transitorio: i valori protetti non devono essere letti, e nessun valore grezzo deve entrare nell'evidenza conservata.
6.3 Mutazioni della sorgente
Preparare tre revisioni dello schema:
- A — iniziale: struttura completa e commenti sorgente valorizzati;
- B — distruttiva: rimozione di una tabella, una colonna e una FK, più aggiunta di una nuova colonna sensibile per nome;
- C — race di conferma: modifica ulteriore fra piano distruttivo e conferma, per provare il re-scan.
Queste revisioni possono vivere nella fixture o in uno schema reale esplicitamente dichiarato scrivibile. Fra una prova e l'altra è consentito eliminare completamente il catalogo locale, riapplicare le migrazioni e ripartire dal database reale.
7. Casi di test — acquisizione dei metadati
| ID | P | Livello | Scenario | Risultato atteso |
|---|---|---|---|---|
| MET-01 | P0 | API/Integrazione | Avvio senza binding raggiungibile, con versione database obsoleta o senza database.manage. |
Il run non parte; risposta sicura e catalogo invariato. I segreti restano write-only. |
| MET-02 | P0 | Integrazione | Reset completo del catalogo e all sul database reale collegato, senza mock del client pg_catalog; ripetizione sulla fixture A per gli edge case assenti. |
Il catalogo viene ricostruito da zero con snapshot esatta di tabelle, colonne, sourceComment, tipo, default, nullabilità, PK e FK ordinate; stato succeeded; nessuna scrittura alla sorgente. |
| MET-03 | P1 | Contratto/Integrazione | Stessa fixture via RPC REST tipizzato. | schemaVersion: 1 e capability sono validate strettamente; risultato normalizzato uguale a MET-02. unavailable non è interpretato come collezione vuota. |
| MET-04 | P0 | Contratto/Integrazione | /schema_snapshot assente, fallback run_query; poi fallback assente, parziale, non JSON o con campi extra/mancanti. |
Il fallback usa una sola query read-only. Ogni errore o snapshot invalida fallisce senza modifiche parziali; nessun fallback nasconde un errore operativo diverso da capability assente. |
| MET-05 | P1 | Integrazione | Accesso ssh_tunnel con host key corretta, errata e assente; errore durante apertura/chiusura. |
Parità con MET-02 nel caso valido; fail-closed negli altri casi; processi, lease e file-segreto sempre rilasciati. |
| MET-06 | P0 | API | Esecuzione separata di tables, columns, relationships e all, con e senza selezione tabelle. |
Ogni scope è autorevole solo nel proprio confine; nessun record fuori scope cambia o viene eliminato. Selezioni duplicate/inesistenti sono rifiutate atomicamente. |
| MET-07 | P0 | API/Integrazione | Ripetizione idempotente della fixture A dopo modifica di description, generatedDescription e sensitive. |
Nessun diff fisico spurio; contenuti curati, proposte AI e flag delle entità ancora presenti sono preservati. Una nuova colonna nasce con sensitive=false. |
| MET-08 | P0 | API/Integrazione | Passaggio A→B, conferma assente/errata/scaduta e passaggio A→B→C prima della conferma. | Stato awaiting_confirmation, piano visibile e nessuna applicazione anticipata. La conferma valida provoca re-scan; se il diff cambia viene emesso un nuovo piano/token e il vecchio non applica nulla. Apply atomica oppure zero modifiche. |
| MET-09 | P0 | API/Integrazione | Timeout, disconnessione, capability incompleta o eccezione durante scan/apply. | Stato terminale coerente, errore sanitizzato, catalogo precedente intatto e lock rilasciato. Nessun segreto, SQL sensibile o stack trace nelle API/eventi. |
| MET-10 | P1 | Worker | Cancel in queued, running, awaiting_confirmation e applying; retry, restart con run attivo e lease scaduto. |
Cancel è efficace solo prima di apply ed è rifiutato durante apply; retry crea un nuovo run. Recovery non duplica l'apply, marca correttamente i run interrotti, rilascia il lock e rimuove snapshot/diff/token interni non più necessari. |
| MET-11 | P0 | API | Due operazioni sullo stesso database: sync, cleanup, connection test, edit o generazione; in parallelo, operazioni su database diversi. | Una sola operazione possiede il database; conflitto 409 sicuro sullo stesso target. Nessun lock cross-database non previsto e nessuna release del token altrui. |
| MET-12 | P1 | UI | Avvio dai menu database/tabella, visualizzazione piano, conferma, history drawer, chiusura drawer, perdita SSE e polling. | Scope e selezione inviati sono esatti; azioni non eleggibili restano visibili con motivo; chiudere il drawer non ferma il run; replay/polling deduplicano gli eventi e aggiornano griglie/KPI. |
| MET-13 | P1 | E2E | Cleanup manuale di tabelle/colonne/relazioni e successiva sincronizzazione. | Cleanup modifica solo il catalogo; la sorgente resta invariata; un sync autorevole ripristina gli oggetti ancora presenti in sorgente. |
| MET-14 | P0 | Integrazione | Cambio binding/versione fra scan e apply ed errore iniettato a metà transazione. | La freshness viene ricontrollata sotto lock; il run fallisce senza righe parziali e conserva integralmente il catalogo precedente. |
| MET-15 | P1 | API/Worker | Replay SSE con Last-Event-ID/after, polling concorrente e retention oltre 30 giorni. |
Cursori monotoni e nessun duplicato; gli eventi scaduti vengono potati senza corrompere run e stato finale. |
8. Casi di test — identificazione e protezione dei campi sensibili
| ID | P | Livello | Scenario | Risultato atteso |
|---|---|---|---|---|
| PRV-01 | P0 | Repository/API | Prima sincronizzazione, re-sync e aggiunta di una colonna. | Il default è false; il valore umano delle colonne esistenti è preservato; la nuova colonna è esplicitamente da riesaminare ma non riceve uno stato audit inventato. |
| PRV-02 | P0 | API | Analisi per un database, tabelle selezionate e colonne selezionate; database multipli, target duplicati o mancanti. | Solo i target dello scope raggiungono l'adapter read-only. Input ambigui sono rifiutati prima della lettura e nessun flag cambia. |
| PRV-03 | P0 | Unit/Contratto | Valori con email, codice fiscale italiano valido, IBAN, carta con Luhn, chiave privata, chiave JSON sensibile e testo oltre 500 caratteri. | Un solo riscontro validato rende l'intera colonna sensitive; l'evidenza contiene solo rule ID e conteggi sanitizzati, mai il valore. |
| PRV-04 | P0 | Integrazione | Scansione completa oltre cinque secondi, timeout PostgreSQL e budget globale di sessanta secondi. | L'adapter passa al campionamento, ripristina la transazione dopo statement_timeout, resta read-only e non supera la deadline. Copertura incompleta senza match produce unknown. |
| PRV-05 | P0 | Unit/API | Tabella vuota, colonna all-null, binario non ispezionabile, scan completo senza match e scan incompleto senza match. | Gli esiti sono rispettivamente unknown, unknown, unknown, non_sensitive e unknown; unknown conserva la scelta umana corrente. |
| PRV-06 | P0 | UI/API | Apertura draft, modifica manuale, chiusura/reload e salvataggio. | La proposta non è persistita prima di Save; reload la scarta. Il reviewer può invertire scelte; si salvano solo colonne cambiate con versione ottimistica; un conflitto richiede reload. |
| PRV-07 | P1 | Repository/UI | Tentativi completati, falliti e attivi al restart. | Ogni tentativo ha un run distinto con scope, engine local, versione policy, tre contatori ed eventi sanitizzati; startup marca interrupted i run attivi. Storico newest-first senza target ID, proposte, valori o diagnostica worker. |
| PRV-08 | P0 | Integrazione | Generazione descrizioni su target con canary protetti. | Le colonne protette sono assenti dalla proiezione SQL, non semplicemente filtrate dopo la lettura. Se non rimangono colonne leggibili non viene eseguita una SELECT. Nessun canary protetto esce dal processo. |
| PRV-09 | P0 | Contratto/Integrazione | Tabella mista con colonne sensibili e pubbliche. | Per le sensibili il prompt contiene valori plausibili, deterministici e limitati derivati dai soli metadati, nello stesso formato dei campioni e senza etichettarli al modello come sintetici. Per le pubbliche: massimo cinque righe e cinque valori rappresentativi, valori troncati e transazione read-only chiusa con rollback. |
| PRV-10 | P1 | API | Cambio false→true→false dopo una descrizione già generata. |
Il testo esistente non viene rigenerato retroattivamente. Solo le generazioni future cambiano fonte del contesto; tornando false il campionamento reale torna eleggibile. |
| PRV-11 | P0 | API/UI | Utente senza database.manage, sorgente/adapter indisponibile, NER assente o in timeout e richiesta interrotta. |
Controlli nascosti/disabilitati in UI e rifiuto server-side; errori non espongono dettagli. Il NER opzionale degrada alle regole/coverage senza selezionare un LLM. |
| PRV-12 | P1 | L2 | Corpus etichettato con identificatori personali, credenziali/token, salute, finanza, localizzazione e controlli non sensibili/ambigui, in inglese e italiano. | Si misurano precisione, recall, falsi negativi, copertura e latenza separatamente per policy deterministica e NER CPU. La soglia va ratificata prima di abilitare NER per default; il classifier resta advisory e human-in-the-loop. |
| PRV-13 | P0 | UI/E2E | Modifica di un flag nella review senza Save e tentativo immediato di generare descrizioni. | Gate di rilascio da formalizzare: la generazione deve essere bloccata finché il draft non è salvato o scartato. In alternativa la UI deve dichiarare inequivocabilmente che verrà usato il valore persistito; non è accettabile mostrare “protetto” e campionare come non protetto. |
9. Casi di test — generazione e consolidamento dei commenti
| ID | P | Livello | Scenario | Risultato atteso |
|---|---|---|---|---|
| GEN-01 | P0 | Config/API | Modelli validi, default, endpoint anonimo esplicito, secret ref mancante/errato e nessun modello. | Al browser arrivano solo ID, label e default. Nessuna chiave, provider payload o configurazione privata è esposta; feature disabilitata in modo comprensibile se non configurata. |
| GEN-02 | P0 | API | selected_columns, selected_tables, all, missing, target duplicati/inesistenti e zero eleggibili. |
Scope esatto; missing include null/vuoto/whitespace e salta proposte esistenti; all sostituisce solo dopo conferma esplicita; input invalido non crea run. |
| GEN-03 | P1 | Worker | 23 colonne più tabelle, metadati e campioni lunghi. | Colonne prima delle tabelle per lo scope globale; richieste omogenee, sequenziali, massimo dieci target e sotto i limiti byte; contesto tabella aggiornato dopo le colonne. |
| GEN-04 | P0 | Contratto | JSON puro, un solo code fence JSON completo, prosa extra, payload multipli, target mancante/duplicato/ignoto, descrizione vuota o oltre limite. | Sono accettati solo i primi due formati validi. Una mappatura ambigua non applica alcun risultato del batch e conta come errore tecnico. |
| GEN-05 | P1 | API | Esito generated e non_generatable in workspace italiano/inglese. |
Testo generato trimmato e salvato; il testo standard non generabile è localizzato dall'applicazione, non copiato dal provider. Gli errori tecnici non scrivono tale testo. |
| GEN-06 | P0 | Worker | Errore transiente, errore esaurito isolato, tre batch falliti consecutivi e successo fra due errori. | Helper con al massimo un retry e nessun fallback modello. Errori isolati portano a completed_with_errors; tre consecutivi a failed; un successo azzera il contatore. |
| GEN-07 | P0 | Integrazione | Successi seguiti da cancel, interruption o failure. | Ogni risultato valido è persistito subito e resta disponibile; il target fallito non riceve dati ambigui. “Generate Missing” consente il recupero naturale senza resume automatico. |
| GEN-08 | P0 | API | Secondo run durante un run attivo e modifica/sync/cleanup/consolidamento sul database posseduto. | Un solo run di generazione attivo nell'installazione; 409 chiaro al secondo Start. Il database target resta riservato e le operazioni incompatibili non alterano selezione o dati. |
| GEN-09 | P0 | Integrazione/Worker/UI | Stop in queued/running con helper attivo e con una SELECT sorgente deliberatamente bloccata/lenta. |
Helper e query/connessione vengono terminati entro 5 secondi, stato cancelled, nessuna chiamata modello dopo Stop, risultati precedenti conservati ed eventi consultabili. Un test con sampler fake non è sufficiente. |
| GEN-10 | P0 | Worker/API | Restart con run queued/running; Unlock con worker/helper vivo e con run realmente stale; race Unlock/Start. |
Startup marca interrupted senza replay. Unlock è rifiutato se esiste lavoro locale vivo e non può liberare la reservation di un nuovo run. |
| GEN-11 | P1 | Integrazione | Sorgente campioni indisponibile ma metadati validi. | La generazione prosegue metadata-only con un solo warning sicuro; nessun tentativo alternativo espone dettagli di connessione. |
| GEN-12 | P1 | API/UI | SSE disconnesso, replay da sequence, polling concorrente e riapertura storico. | Eventi persistiti, ordinati e deduplicati; history newest-first; contatori/stato finali coerenti; nessun prompt, campione, risposta completa o stack trace. |
| GEN-13 | P0 | UI/API | Revisione manuale della proposta e consolidamento selettivo di tabelle/colonne, inclusi target vuoti/stale. | Si copia solo generatedDescription non vuota dei target risolti; conteggio copied/skipped corretto; operazione atomica; sourceComment invariato. |
| GEN-14 | P0 | UI/Sicurezza | Tutti gli scope di generazione da database, tabelle e colonne selezionate, utente senza permesso, metadata contenente istruzioni ostili. | Prima di ogni Start, inclusi selected_tables e selected_columns, compare la disclosure “fino a cinque righe e cinque valori”. Il server applica comunque l'autorizzazione. Metadati e valori sono trattati come dati non fidati e l'output resta nel contratto JSON. |
| GEN-15 | P1 | L2 | Run reale sul modello di default e almeno un endpoint alternativo supportato, usando il database reale dopo la review dei flag e un role read-only. | Descrizioni nella lingua workspace, coerenti con struttura/commenti e senza fatti inventati critici; almeno una colonna e una tabella consolidate. Nessun valore protetto o segreto compare in request osservabile, eventi, API, persistenza o log. |
| GEN-16 | P1 | Integrazione | Fastify→worker→processo Python→LiteLLM→endpoint OpenAI-compatible locale di cattura. | Routing provider/model, header API key, disableThinking, singolo retry, timeout, limite output e payload sono corretti; chiave e diagnostica non risalgono a stdout, API o log applicativi. |
10. Percorso E2E prioritario
Il caso E2E-01 deve attraversare le tre feature senza sostituire i test di contratto:
- azzerare
catalog-db, riapplicare le migrazioni e verificare che il role del database reale sia realmente read-only; - eseguire
allsul database reale e confrontare catalogo e snapshot sorgente; usare la fixture A in una seconda esecuzione per gli edge case mancanti; - richiedere suggerimenti privacy sull'intero database;
- modificare almeno una proposta e salvare i flag revisionati;
- avviare
missingdopo la disclosure, usando un Model Completer osservabile; - dimostrare che i canary protetti non sono letti né inviati e che il canary pubblico rispetta i limiti;
- correggere una
generatedDescriptione consolidare una tabella e una colonna; - applicare la fixture B, controllare il piano distruttivo e introdurre C prima della conferma;
- confermare dopo il re-scan e verificare atomicità, preservazione di descrizioni/flag delle entità
superstiti e
sensitive=falsesulla nuova colonna; - perdere la connessione SSE, riaprire entrambi gli storici e verificare replay, polling e KPI.
Il percorso deve essere eseguito con fake provider dopo ogni reset rilevante e, in forma ridotta, con il provider configurato sul database reale dopo che i flag sono stati revisionati e salvati. Non è richiesto ripristinare lo stato locale precedente al test.
11. Valutazione qualitativa dei modelli
La qualità non deve confondersi con la sicurezza: anche un classifier perfetto non autorizza l'esfiltrazione di un canary protetto e una descrizione elegante non rende valido un payload ambiguo.
11.1 Classificazione privacy
Per ogni modello registrare matrice di confusione, precisione, recall e falsi negativi per categoria. Eseguire almeno tre iterazioni sul corpus fisso per rilevare instabilità. Fino alla ratifica di una soglia da parte del product owner, il risultato è un gate di review: ogni falso negativo su credenziali/token, identificatori fiscali, dati sanitari o finanziari richiede accettazione esplicita o correzione prima del rilascio operativo.
11.2 Descrizioni generate
Valutare ogni testo da 0 a 2 su:
- correttezza rispetto a struttura e commenti sorgente;
- specificità e utilità per un revisore;
- lingua e chiarezza;
- assenza di istruzioni seguite dai dati non fidati o fatti inventati;
- assenza di valori protetti e segreti.
Soglia proposta da ratificare: almeno 8/10, nessun punteggio 0 su correttezza o sicurezza. Un valore esplicitamente non sensibile, reale o inventato, può essere ripreso entro il perimetro dichiarato; un valore protetto non può mai esserlo.
12. Copertura esistente e gap da chiudere
| Area | Evidenza automatica già presente | Gap principale |
|---|---|---|
| Snapshot e sincronizzazione | backend/test/catalog-schema-introspector.test.ts, catalog-schema-routes.test.ts, catalog-table-introspector.test.ts, catalog-repository.integration.test.ts |
Introspezione pg_catalog realmente end-to-end, parità live dei tre trasporti e un unico E2E con re-scan distruttivo. |
| Privacy | catalog-sensitivity-classifier.test.ts, catalog-sensitivity-value-source.test.ts, catalog-local-ner-detector.test.ts e i test di route/review |
Prova shadow PSD con report solo aggregato, corpus italiano etichettato e benchmark NER CPU post-ADR 0014. |
| Generazione | catalog-description-generation-routes.test.ts, catalog-description-generation-worker.test.ts, catalog-description-generation.integration.test.ts e test del helper |
Accettazione reale aggiornata, cancellazione di una query PostgreSQL bloccata e integrazione ermetica fino all'endpoint LiteLLM locale. |
| UI | DatabaseManagementPage.test.tsx, DescriptionGenerationDrawer.test.tsx, SensitivityAnalysisHistoryDrawer.test.tsx |
L'E2E Playwright corrente verifica soprattutto il layout, non il workflow funzionale. |
Nuovi asset consigliati:
backend/test/catalog-metadata-privacy-workflow.integration.test.ts;backend/test/fixtures/catalog-privacy-schema.sqle snapshot REST equivalenti;- integrazione a due PostgreSQL per le query reali
pg_cataloge lo stop del sampler; - endpoint OpenAI-compatible locale di cattura per GEN-16;
frontend/e2e/database-management-workflow.spec.ts;- corpus strutturale versionato per PRV-12, senza valori business;
- nuovo report di accettazione L2 che sostituisca il gate privacy del 2026-08-29.
13. Ordine di esecuzione
Wave 1 — contratto rapido
- parser snapshot, introspector, scope e diff;
- classifier locale, validatori/checksum, copertura e fallback al campionamento;
- sampler, valori sintetici, prompt bounds e parser descrizioni;
- autorizzazione, redazione e race del coordinator.
Wave 2 — integrazione PostgreSQL
- reset totale di
catalog-db, bootstrap delle migrazioni e ricostruzione dal database reale; - migrazioni e vincoli del repository;
- atomicità sincronizzazione/consolidamento;
- run ed eventi persistiti, restart e cancellation;
E2E-01con fake provider e canary.
Wave 3 — frontend e stack locale
- component test MSW;
- Playwright funzionale, perdita SSE e polling;
- verifica disclosure, review draft, history e consolidamento.
Wave 4 — accettazione L2
- analisi shadow sul database collegato e review dei flag, senza scritture in sorgente;
- benchmark NER CPU PRV-12 e rubric GEN-15 per la generazione descrizioni;
- scansione finale di canary e segreti;
- approvazione del product owner.
Comandi di regressione:
cd backend && npx vitest run
cd backend && npx tsc --noEmit -p .
cd backend && npm run build
cd frontend && npx vitest run
cd frontend && npx tsc -b
cd frontend && npm run build
cd frontend && npm run e2e
./scripts/build-docs.sh
Il report deve evidenziare esplicitamente eventuali test Docker/L2 saltati; un skip non equivale a
PASS del relativo gate.
14. Evidenze da conservare
Per ogni esecuzione registrare:
- commit, configurazione pubblica dei modelli, versione fixture e trasporto;
- ID e stato finale dei run, contatori ed eventi sanitizzati;
- snapshot catalogo prima/dopo e piano distruttivo con metadati e conteggi sanitizzati, senza valori grezzi delle righe sorgente;
- report test/JUnit, screenshot dei gate UI e risultato della scansione canary;
- matrice di confusione privacy e rubric delle descrizioni per le prove L2;
- difetti con ID del caso, severità, riproducibilità e decisione finale.
Non allegare prompt completi, righe campione, output grezzi del provider, chiavi, digest o frammenti di segreti. Il Model Completer spy deve verificare in memoria le asserzioni e scartare il payload al termine del test.
Non serve conservare backup del catalogo locale, run precedenti o descrizioni generate durante una wave: l'evidenza è il report sanitizzato e la capacità di ricostruire nuovamente il risultato dalla sorgente reale.
15. Criteri di ingresso e uscita
Ingresso
- baseline unica per backend/frontend e procedura verificata per eliminare e ricreare
catalog-db; - accesso al database reale collegato e inventario delle tabelle/colonne da includere nella review;
- fixture e canary supplementari approvati per i soli edge case controllati;
- role sorgente read-only verificato con una scrittura deliberatamente negata;
- fake connector/provider disponibili e log collection attiva;
- per L2, secret reference configurato senza materializzare il valore nell'evidenza.
Uscita
- 100% dei casi P0 e P1 applicabili superati; nessun difetto Sev-1/Sev-2 aperto;
- almeno due ricostruzioni complete e coerenti del catalogo a partire dal database reale dopo reset indipendenti;
- zero comparsa dei canary protetti e dei segreti fuori dalla sorgente/secret store del test;
- nessuna modifica parziale dopo errori, cancel o conferme stale;
- parità normalizzata dei trasporti supportati e nessuna integration PostgreSQL richiesta saltata;
- stati, contatori, eventi e history coerenti dopo success, partial failure, stop e restart;
sourceComment,generatedDescriptionedescriptionmantengono l'autorità prevista;- accettazione L2 sul database collegato approvata dal product owner e build/test/typecheck/documentazione verdi;
- ogni deviazione P2 o soglia qualitativa non ancora ratificata è documentata con owner e data.
16. Rischi residui da rendere espliciti
sensitive=falseè il default e il prodotto non conserva uno stato “review completata”: dopo ogni reset, classificazione strutturale e salvataggio umano dei flag devono precedere qualunque run con provider reale. Il catalogo è ricostruibile; un invio errato a un provider non lo è.- Il flag protegge i valori campionati. Nomi,
sourceCommente descrizioni sono metadati inviabili al modello e possono contenere testo libero: se nel database reale includono PII serve una decisione aggiuntiva di redazione, non una diversa aspettativa di test. - La UI deve risolvere il caso di un flag modificato ma non salvato prima della generazione e deve mostrare la disclosure anche per tabelle/colonne selezionate; il piano considera entrambi P0.
- L'AbortSignal corrente va provato contro una query PostgreSQL realmente bloccata: la sola cancellazione del helper non dimostra che la lettura sorgente sia interrompibile.
- Lo storico dei Sensitivity Analysis Run è operativo, non un audit delle decisioni umane.
- La policy privacy non è ancora applicata allo schema-linking/LSH; nessun risultato di questo piano deve essere presentato come copertura di quel percorso.
- Un provider reale resta non deterministico: il rilascio deve dipendere dai gate tecnici e dalla review umana, non dalla ripetizione byte-identica delle descrizioni.
- L'esclusione fra operazioni e Unlock è in parte locale al processo. Se il deployment ammetterà più repliche backend, servirà un gate aggiuntivo con due istanze contro lo stesso catalogo; non va dedotta sicurezza multi-replica dai test single-process.