Files
ThothII/docs/testing/2026-08-31-metadata-privacy-description-test-plan.md
T
2026-09-15 14:37:29 +02:00

34 KiB

Piano di test: metadati di schema, campi sensibili e descrizioni AI

  • Data: 2026-08-31
  • Stato: proposto
  • Baseline analizzata: f586152 sul branch test/database-baseline

1. Obiettivo

Validare insieme le tre capacità recentemente introdotte in Database Management:

  1. acquisizione autorevole dei metadati fisici di uno schema esterno;
  2. proposta e revisione umana dei campi sensibili dal punto di vista privacy;
  3. 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:

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_api e ssh_tunnel;
  • RPC REST tipizzato POST /rpc/schema_snapshot e fallback singolo read-only su POST /rpc/run_query;
  • metadati di tabelle, colonne, commenti sorgente, tipi, default, nullabilità, posizioni PK e coppie FK ordinate;
  • scope di sincronizzazione tables, columns, relationships e all;
  • 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, all e missing;
  • 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:

  1. Contratto/unità: repository in memoria, finti connector e Model Completer; nessuna rete.
  2. Integrazione: catalogo PostgreSQL ricreabile via Docker, database reale come sorgente, fixture supplementare, fake REST/SSH e Model Completer osservabile.
  3. UI/E2E locale: component test con MSW e almeno un flusso Playwright sullo stack locale.
  4. 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-db eliminabile, migrazioni ripetibili e backend/frontend della stessa baseline;
  • database reale già collegato come sorgente primaria, con utenza capace di SELECT ma non di INSERT, 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 fallback run_query;
  • server OpenSSH effimero con known_hosts esatto 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 verso customers, 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 batch 10 + 10 + 3 e 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:

  1. azzerare catalog-db, riapplicare le migrazioni e verificare che il role del database reale sia realmente read-only;
  2. eseguire all sul database reale e confrontare catalogo e snapshot sorgente; usare la fixture A in una seconda esecuzione per gli edge case mancanti;
  3. richiedere suggerimenti privacy sull'intero database;
  4. modificare almeno una proposta e salvare i flag revisionati;
  5. avviare missing dopo la disclosure, usando un Model Completer osservabile;
  6. dimostrare che i canary protetti non sono letti né inviati e che il canary pubblico rispetta i limiti;
  7. correggere una generatedDescription e consolidare una tabella e una colonna;
  8. applicare la fixture B, controllare il piano distruttivo e introdurre C prima della conferma;
  9. confermare dopo il re-scan e verificare atomicità, preservazione di descrizioni/flag delle entità superstiti e sensitive=false sulla nuova colonna;
  10. 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.sql e snapshot REST equivalenti;
  • integrazione a due PostgreSQL per le query reali pg_catalog e 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-01 con 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, generatedDescription e description mantengono 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, sourceComment e 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.