Fix/mvvm view callbacks - #10
Merged
Merged
Conversation
…iviso con registry per dominio, tabella workflow_tasks polimorfica e propagazione del correlation id nel worker
…azioni, sostituendo la colonna base64 con path su storage, enum dedicati e colonne di workflow
…age a oggetti, prompt visivo scritto dal modello testuale, upload manuale su POST e stream SSE di avanzamento
…dicate, worker separato e client Bedrock immagini su region propria
…n stati espliciti della copertina e ripristino dell'empty state
…incluso il degrado della copertina che non invalida la bozza
…ona delle comunicazioni e alla nuova struttura dei servizi
…lle comunicazioni AI Assistant Implementa UC-6 (rigenera bozza mantenendo prompt/tono/stile), UC-7 (scarto con conferma, che esclude la bozza dallo storico attivo) e UC-23 (eliminazione definitiva di un elemento dello storico, con conferma).
…ente TestBed di Jest
… con le colonne allineate al controller
…, non all'anteprima
… tenant, validazione e paginazione
…le porta nelle dashboard
Refactor/UI ux
Lo scroll (Overview, Assistant) passa da una callback nel costruttore del ViewModel a un segnale osservato dalla View (pendingScrollTarget), chiudendo l'unica violazione MVP rimasta nel pattern. L'anteprima del documento selezionato si sposta da sub-document-list.ts al ViewModel della pagina Copilot, cosi' nessun componente figlio parla piu' con un servizio dati bypassando il VM. Aggiunge anche una guardia anti-concorrenza a MvpStateStore.reload(), assente rispetto a loadOnce().
copilot.duration/assistant.duration (istogramma con mediana su dieci intervalli) e copilot.processing_seconds/assistant.generation_seconds (media per fase con residuo di orchestrazione) diventano una singola media in secondi, calcolata sulle stesse durate gia' raccolte da workflowDurations(). Le tre ripartizioni per categoria (review, download, field_confidence) restano invariate. Rimuove di conseguenza i due componenti Angular diventati privi di utilizzo (metric-distribution, metric-phases) e gli helper di charts.ts usati solo da loro; MetricPart trasloca in metric-breakdown.ts, l'unico consumatore rimasto.
Elimina App\Mvp\Observability (DomainMetricCatalog, PrometheusExporter, DlqDepthProbe, MetricsRecorder), l'endpoint /internal/metrics e il middleware RecordHttpMetrics: lo stack di monitoraggio operativo (vedi commit successivo per Docker/CI) e' sovradimensionato per la scala del progetto, allineato a un modello AWS di produzione mai raggiunto qui. Le chiamate a recordDomainCounter()/recordHttp() sono rimosse dai punti di strumentazione (listener di dominio, adapter, worker) senza toccare la logica di business che le circondava; due listener esistevano solo per registrare una metrica e sono stati eliminati per intero. Restano invariati l'audit log di compliance e i correlation ID, che l'ADR 0006 descriveva nello stesso documento ma non condividono codice con lo stack rimosso.
…osso Segue il commit precedente (rimozione di App\Mvp\Observability): sistema la parte che lo orchestrava. docker-compose.yml perde i sette servizi osservabilita', la rete dedicata e i relativi volumi; traefik resta solo router di edge, senza piu' instradare le dashboard ne' esporre le proprie metriche Prometheus. nginx smette di servire /internal/metrics sia sul listener pubblico che su quello interno :8081, ormai senza piu' nulla da esporre. La CI perde lo step di validazione OTel/Prometheus e i controlli smoke sulle dashboard; lo script di mirror immagini non elenca piu' i sette servizi rimossi.
Aggiunge l'ADR 0014, segna come superata la parte di ADR 0006 su OTel/Prometheus/Grafana (l'audit trail resta accettato), ed elimina il runbook e i diagrammi dedicati. Aggiorna i runbook operativi ancora in uso (local-development, dlq-recovery, ci-cd, le due pipeline) perche' non indichino piu' comandi o dashboard che non esistono. Corregge anche la tracciabilita' verso il Capitolato: il requisito "CloudWatch Logs/Metrics/Alarms, X-Ray" era coperto per intero dallo stack rimosso, ora lo e' solo in parte (audit trail e log strutturati restano, l'equivalente locale di Metrics/Alarms/X-Ray no) — segnalato esplicitamente invece di lasciare la mappatura invariata. IMPLEMENTATION_OVERVIEW.md, essendo un'analisi puntuale datata, riceve una nota di cappello invece di una riscrittura integrale delle sezioni di dettaglio; i punti a piu' alta visibilita' (sommario, mappa della codebase, diagramma di architettura) sono comunque aggiornati.
…-27, UC-56) Le due dashboard mostravano metriche operative (generazioni/elaborazioni fallite o bloccate, copertine non riuscite, ripartizioni di stato) mai richieste da nessun caso d'uso del documento di Analisi dei Requisiti, e ne mancavano alcune esplicitamente richieste: il conteggio delle configurazioni di prompt salvate (UC-27.1), l'elenco dei feedback testuali recenti (UC-27.3), la percentuale di classificazioni corrette senza intervento manuale (UC-56.2) e quella dei destinatari riconosciuti in automatico (UC-56.4). Per UC-56.4 il confronto usa `ai_payload`, lo snapshot immutabile scritto una sola volta da ExtractSubDocumentFieldsService e mai più toccato da una correzione manuale (verificato che quest'ultima scrive solo le colonne tipizzate): un sotto-documento conta come "riconosciuto correttamente" solo se l'AI ha davvero letto qualcosa (altrimenti due campi assenti su entrambi i lati passerebbero per una corrispondenza) e quel qualcosa coincide ancora coi valori correnti. Rimosse le metriche non richieste sia dal backend (dove il codice che le calcolava è sparito insieme a loro) sia dalla presentazione frontend; `copilot.ocr_confidence` resta nel contratto ma esce dal pannello perché la Overview la legge ancora. Le etichette del "resto" nelle schede a quota (`auto_classified`, `needs_review`) descrivono ora solo ciò che è vero per l'intero insieme che rappresentano, non solo per il caso più comune. Nuovo componente RecentFeedbackListComponent per UC-27.3, con un'etichetta per scheda (non condivisa) per restare distinguibile a uno screen reader anche con più voti in elenco.
Una revisione ha trovato tre problemi in "recipient_auto_matched" e "auto_classified" già in produzione: un sotto-documento in cui l'AI non aveva riconosciuto nulla del destinatario passava per una corrispondenza riuscita (due assenze non sono un successo); il denominatore di "auto_classified" era l'intero conteggio dei sotto-documenti, diluendo la percentuale con quelli ancora da revisionare o in quarantena — che non sono né un successo né un fallimento della classificazione automatica, sono semplicemente non conclusi. Sistemando quest'ultimo è emersa la stessa contaminazione anche in "needs_review": un sotto-documento nasce con review_status a "needs_review" per default, prima ancora che la sua estrazione giri (ProcessDocumentService crea la riga e solo dopo la estrae), quindi in un documento con più destinatari un segmento in coda può risultare "sotto soglia" per un motivo che non ha nulla a che fare con la confidenza. La distinzione ora si basa sulla presenza di ExtractedData, scritta solo quando l'estrazione è davvero girata (la quarantena la cancella): sia "needs_review" che il denominatore di "auto_classified" contano solo i sotto-documenti valutati per davvero. Le etichette del "resto" nelle schede a quota sono state riallineate a questi denominatori corretti, e il mosaico del pannello Co-Pilot è stato riordinato: la griglia CSS non ricompone da sola le righe per colmare i vuoti, quindi l'ordine delle schede conta quanto il loro numero di celle — le due strette ora precedono le tre larghe, così le righe si chiudono senza spazi vuoti (lo stesso valeva, inosservato, per il pannello Assistant).
…che EMF (RVC16-OB, ADR 0015) Dopo la rimozione dello stack self-hosted (ADR 0014), reintroduce un riscontro a RVC16-OB con la minima superficie operativa possibile: i log JSON strutturati esistenti (CorrelateRequests) restano instradabili verso CloudWatch Logs via log driver del container, e le metriche (traffico, latenza, errori per richiesta, profondita' DLQ) vengono emesse in formato CloudWatch Embedded Metric Format su un canale di log dedicato, senza endpoint di scrape ne' collector. RecordRequestMetrics ascolta RequestHandled invece di essere un middleware: un'eccezione che risale la pipeline (validazione, autorizzazione, 500) verrebbe tradotta in risposta fuori dalla pipeline stessa, e il codice dopo $next() in un middleware non verrebbe mai eseguito - proprio il caso che la metrica Errors deve intercettare.
…ioni mancanti (RF34, RF56, RF95, RF101/102/105) - RF34-OB: export PDF del report riepilogativo della dashboard AI Assistant (AssistantMetricsReportController/Renderer), riusando i dati gia' calcolati da MvpStateService::assistantState() e lo stack Dompdf gia' in uso. - RF56-OB: anteprima del documento originale non splittato (UC-40.2), nuovo metodo previewOriginal() su PreviewDocumentUseCase/Service, link "Documento originale" nel dettaglio sotto-documento, indipendente dallo stato dell'anteprima splittata cosi' resta un'alternativa reale quando quella fallisce. - RF95-OB: validazione email sul destinatario del messaggio di invio (UpdateSendMessageRequest + frontend), con un validator condiviso (emailValidator) che tollera gli spazi di contorno tagliati al salvataggio - applicato anche a recipientEmail, che aveva lo stesso bug latente. - RF101/102/105-OB: nome/cognome, azienda e descrizione mostrano "Non disponibile" invece di un campo vuoto quando mancano, restando modificabili in edit mode. Aggiunge test di dominio puro per previewOriginal() (prima assenti, a differenza del preview() gemello) ed estende InMemoryDocumentRepository/ OriginalDocumentRecord con originalFilename.
…F41-OB) Nella sezione Metriche dell'AI Assistant, un filtro separato da quello dello storico permette di restringere per tono, stile e intervallo di date; i numeri Co-Pilot restano sempre sul totale del tenant, dato che tono e stile non esistono sui documenti. Corregge anche un ciclo di richieste infinito nello store (effect() che leggeva e riscriveva lo stesso segnale di loading), risolto con untracked().
…x/mvvm-view-callbacks # Conflicts: # apps/frontend/src/app/features/assistant/assistant-page.ts # apps/frontend/src/app/features/assistant/assistant-page.view-model.spec.ts # openapi/v1/alittlebyte-mvp-api.yaml
Tre effect() (Co-Pilot sub-document-list, Assistant generated-communication- preview, communication-generator-panel) risincronizzavano il form ad ogni nuovo riferimento dell'input sorgente, non solo quando il dato osservato cambiava davvero: qualunque mutazione altrove nella pagina (un preferito, una revisione, un'eliminazione) rimpiazza lo stato condiviso e produce un nuovo riferimento anche per l'elemento su cui si sta scrivendo, cancellando silenziosamente modifiche non salvate. Ora ciascun effect confronta id o contenuto prima di risincronizzare. Corregge anche reloadFilteredAssistantMetrics() (RF38-OB): un cambio di filtro mentre il precedente e' ancora in volo annullava la nuova richiesta invece di sostituire quella vecchia, perdendo il filtro piu' recente. Trovati da una revisione indipendente su tutto il frontend.
…kend Trovati da una revisione indipendente su tutto l'applicativo (dominio, HTTP/Support, contratto OpenAPI): - Race condition su approvazione/scarto bozza (CommunicationDraftService): update()/save()/discard() ora usano lock pessimistico + transazione come favorite()/unfavorite(), altrimenti due richieste quasi simultanee potevano far vincere l'ultima a scrivere, bypassando l'invariante di dominio "una bozza scartata non torna approvata". - Doppio avvio del workflow AI/OCR (StartCommunicationWorkflowService, StartDocumentWorkflowService): il controllo "e gia in corso?" e la scrittura che lo rende vero ora girano nello stesso lock, altrimenti due richieste ravvicinate potevano avviare due esecuzioni Step Functions per la stessa comunicazione/documento. - Difesa in profondita sul tenant per le mutazioni di Communications (favorite/unfavorite/update/save/discard, delete, rate, cover update/remove): oggi il controllo HTTP le protegge tutte, ma un caso d'uso applicativo non dovrebbe fidarsi solo di chi lo chiama (stesso principio gia in uso per Documents e PromptConfiguration). - ExtractedDataChanges::fromRawFields() rifiuta ora campi fuori dalla whitelist dei dieci correggibili manualmente, invece di accettare qualunque chiave. - SendMessageController non costruisce piu a mano le risposte d'errore: i due domain exception passano dal gestore centralizzato in bootstrap/app.php, cosi portano sempre requestId/correlationId come ogni altro errore dell'app. - Contratto OpenAPI allineato al comportamento reale: 403 dichiarato sulle 6 rotte Documents che lo applicano davvero (stream, delete, preview, original-preview, send-preview, send-export), 422 dichiarato per le ultime due; aggiunti i due test di contratto e i due test cross-tenant mancanti (stream, delete) che l'avrebbero gia intercettato. - Content-Disposition dei preview documento ora rimuove anche i caratteri di controllo (CR/LF inclusi) dal nome file, non solo le virgolette.
…o, non contenuto) Trovati da una seconda revisione indipendente, dopo il primo giro di correzioni: - generated-communication-preview.ts: l'effect che chiude la conferma "Scarta bozza" si resettava su ogni nuovo riferimento di draft(), non solo quando la bozza cambiava davvero — stesso bug gia' corretto sui due effect vicini nello stesso file, rimasto su questo terzo. Ora confronta l'id, come gli altri. - copilot-page.ts: il commento diceva "non legge currentPage() apposta per non duplicare la richiesta a cambio pagina", ma vm.reload() la legge comunque al suo interno, diventando una dipendenza nascosta dell'effect che lo chiama. Ogni click su "pagina successiva" scatenava due richieste invece di una. Corretto con untracked(), stesso schema gia' usato in mvp-state.store.ts.
…ficabile dai test Trovati da una seconda revisione indipendente, dopo il primo giro di correzioni: - StartCommunicationWorkflowService::regenerate() riceveva gia' l'Actor ma non lo usava per il controllo tenant, a differenza di tutti i suoi metodi fratelli. L'Actor non e' piu' nullable (l'unico chiamante HTTP ne passa sempre uno reale). - ReviewDocumentService (correzione dati estratti + marca come revisionato) non aveva nessun controllo tenant, a differenza degli altri casi d'uso del modulo Documents. Stesso trattamento: Actor obbligatorio, controllo contro l'originale del sotto-documento. - Aggiunti i test diretti mancanti per update()/discard()/unfavorite() di CommunicationDraftService (avevano solo save()/favorite()). - I due test sull'errore di SendMessageController ora verificano anche che requestId/correlationId siano davvero presenti in risposta, non solo error.code — l'unica cosa che quella correzione doveva garantire. - I fake InMemoryCommunicationRepository/InMemoryDocumentRepository ora contano le letture passate da findXForUpdate(): senza, un futuro regresso che rimuovesse il lock pessimistico (tornando a findX()) non avrebbe fatto fallire nessun test, perche' le due implementazioni nel fake erano identiche. Aggiunto l'assert su questo contatore ai test che esercitano i metodi protetti dal lock (favorite/save/discard di CommunicationDraftService, start() di entrambi gli StartXWorkflowService).
Import non in ordine alfabetico in CommunicationDraftService.php, indentazione della continuazione @throws non allineata in ExtractedDataChanges.php.
… codebase Backend (Communications, Documents, HTTP/Support/Workflow) e frontend (core, shared, layout, features) mantengono solo il perche' non ovvio in 1-2 righe; tolte le narrazioni "prima faceva X, ora fa Y" e i docblock che ripetevano in prosa citazioni RF/UC/ADR gia' presenti. Nessuna modifica di logica: verificato con pest (495 passed), pint (413 file), frontend lint/typecheck e jest (510 passed). Include anche le assertion su forUpdateReadCount() in RateCommunicationServiceTest, rimaste non commitate da una sessione precedente.
…rivy in CI Dipendenza transitiva di laravel/framework (vincolo ^2.8.1, gia' compatibile con 2.10.0): la scansione immagine in CI segnalava GHSA-8rr7-cvq3-gmfh, GHSA-f8fg-pg57-v4j8, GHSA-j8pm-gj4c-rq4x e GHSA-jjv6-8j6v-6j52 (DoS/XSS) sulla 2.9.0. Aggiornate anche nette/schema, nette/utils e mtdowling/jmespath.php come conseguenza della risoluzione delle dipendenze. Verificato: pest (495 passed), scansione Trivy sull'immagine di produzione pulita.
angelica-gastal
approved these changes
Sep 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.