Androidiani.net - Forum

Androidiani.net è la community italiana sul mondo Android. Questo è il forum ufficiale basato su NodeBB e federato con ActivityPub: il punto da cui riparte la community più grande d'Italia su Android, che fa parte del Fediverso


  • 0 Votazioni
    1 Post
    0 Visualizzazioni
    blog@spcnet.itB
    Con la versione 2.1.224, rilasciata la prima settimana di agosto 2026, Claude Code introduce la messaggistica tra sessioni: due o più istanze del CLI, avviate in terminali diversi, possono ora scambiarsi messaggi di testo senza che sia l’utente a fare da tramite copiando e incollando contesto da un terminale all’altro. È una funzionalità pensata per chi lavora abitualmente con più sessioni parallele su worktree diversi dello stesso repository, e merita attenzione anche solo per capire come configurarla in modo sicuro in un contesto aziendale.Il problema che risolveChi usa Claude Code su progetti complessi finisce spesso per aprire più terminali: uno per il lavoro principale, uno per un hotfix urgente, uno per un refactoring in un worktree separato. Fino a v2.1.223 l’unico modo per far sapere a una sessione cosa stava succedendo in un’altra era manuale: copiare un riassunto, incollarlo, ripetere il contesto. La messaggistica cross-session automatizza esattamente questo passaggio.Due strumenti nuovi: ListAgents e SendMessageClaude Code espone due tool interni che il modello usa autonomamente, senza che l’utente li invochi direttamente:ListAgents individua le sessioni raggiungibili: subagent nella sessione corrente, altre sessioni locali sulla stessa macchina (incluse quelle in background) e sessioni remote se è attiva la Remote Control.SendMessage consegna un messaggio di testo a una sessione specifica, identificata per nome.Il messaggio non è mai la cronologia della conversazione né un file: è un testo che una Claude scrive per un’altra Claude. Per spostare davvero un intero contesto conversazionale tra terminali resta lo strumento giusto il resume di sessione, non la messaggistica.Per vedere quali sessioni sono raggiungibili basta lanciare, in un terminale con Claude Code attivo:/list-agentsIl comando elenca ogni sessione con il nome a cui risponde (derivato dalla cartella di lavoro, oppure impostato con /rename o il flag --name), utile per distinguere sessioni omonime che girano in directory diverse.Come si usa in praticaNon si compone il messaggio a mano: si dice a Claude cosa si vuole che l’altra sessione sappia, ed è Claude a scrivere il riassunto effettivo. Due esempi di prompt tipici:Chiedi alla sessione nell'altro terminale se la migrazione è terminataSpiega alla sessione che lavora sulle API di pagamento cosa abbiamo appena cambiatoNel secondo caso il contenuto esatto del messaggio varia: è Claude a decidere come riassumere il lavoro fatto. Quando il messaggio arriva, compare nella conversazione della sessione ricevente con il nome del mittente, e viene compattato in una riga Message from che si espande con Ctrl+O.Dove viaggia il messaggioIl percorso dipende da dove gira la sessione di destinazione:Stessa macchina: il messaggio passa attraverso un socket per-sessione, mai attraverso i server Anthropic. In questo caso sono possibili sia nuovi messaggi sia risposte.Altra macchina dell’utente: il messaggio passa dai server Anthropic e arriva tramite la connessione Remote Control di quella macchina. Da qui è possibile solo rispondere, non avviare una conversazione.Claude Code on the web: stesso discorso, solo risposte.Ogni sessione si registra su disco e apre un proprio “inbox socket”: due sessioni si trovano a vicenda solo se vedono lo stesso filesystem, il che significa che una sessione dentro un container e una sull’host non possono raggiungersi, mentre due sessioni nello stesso container sì.Controllo dei messaggi in arrivoPer un uso in ambienti con requisiti di governance, il parametro di configurazione rilevante è crossSessionInbound, impostabile su tre valori:{ "crossSessionInbound": "accept" }accept: ogni messaggio viene consegnato direttamente.hold: Claude Code mostra un avviso ma non consegna nulla, finché l’utente non approva.refuse: il messaggio viene scartato senza notifica al destinatario.Quando non è impostato alcun valore, Claude Code decide messaggio per messaggio in base alla modalità di permessi delle due sessioni: se la sessione ricevente richiede conferma per i permessi, il messaggio viene consegnato; se la sessione ricevente salta le conferme (modalità bypassPermissions), il messaggio viene messo in attesa di approvazione, a meno che anche il mittente dichiari di essere in bypass.Per richiedere sempre un’approvazione esplicita prima che un messaggio lasci la macchina locale, si può impostare:{ "isolatePeerMachines": true }Per disattivare del tutto la funzionalità a livello di organizzazione, nelle managed settings:{ "permissions": { "deny": ["SendMessage", "ListAgents"] }, "crossSessionInbound": "refuse" }Cosa una sessione remota non può fareUn messaggio in arrivo da un’altra sessione non equivale mai al consenso dell’utente: non può approvare un prompt di permesso in sospeso, non può modificare impostazioni di permessi o il file CLAUDE.md, ed eventuali comandi contenuti nel testo (ad esempio /compact) vengono trattati come testo normale, mai eseguiti. Se agire sul messaggio richiede un permesso che la sessione ricevente non ha, scatta comunque il prompt standard.I limiti attualiLa limitazione più rilevante per chi lavora su Windows: la messaggistica cross-session funziona su macOS e Linux, inclusa una sessione Linux dentro WSL 2, ma non su Windows nativo. È inoltre assente su Amazon Bedrock, Claude Platform su AWS, Google Cloud Agent Platform e Microsoft Foundry. Restano infine due limiti strutturali: i messaggi sono solo testo semplice (i protocolli strutturati degli agent team restano interni al team) e i loop di messaggi vengono limitati automaticamente, con un massimo di 50 messaggi accettati in attesa di lettura per sessione.Quando ha senso usarlaLa documentazione ufficiale indica quattro casi d’uso principali: passare un finding da una sessione a un’altra dopo una scoperta rilevante, coordinare worktree paralleli sullo stesso repository, far riportare lo stato di un’operazione lunga (una migrazione, una suite di test) alla sessione che la sta monitorando, e rispondere a messaggi arrivati da sessioni su altre macchine o dal web. Per chi lavora già con più terminali aperti sullo stesso progetto, è una funzione che elimina una frizione reale, a patto di capire bene i default di crossSessionInbound prima di usarla in un ambiente con permessi sensibili.Fonte: documentazione ufficiale Claude Code – Cross-session messaging.
  • 0 Votazioni
    1 Post
    0 Visualizzazioni
    blog@spcnet.itB
    Perché le password su SSH sono ormai un rischio da eliminareSe gestisci anche un solo server Linux esposto su Internet, i log di /var/log/auth.log te lo confermano ogni giorno: bot e botnet tentano continuamente il login SSH via password, in modalità brute-force o credential stuffing. Una password, per quanto complessa, resta un segreto condiviso che può essere intercettato, indovinato o riutilizzato da un attaccante che l’ha ottenuta altrove. L’autenticazione a chiave pubblica elimina questo vettore alla radice: il server non conosce mai un segreto trasmissibile, ma verifica solo che il client possieda la chiave privata corrispondente a una chiave pubblica già autorizzata.Questa guida copre il flusso completo: generazione della coppia di chiavi con ssh-keygen, distribuzione della chiave pubblica, gestione di host multipli con ~/.ssh/config, uso di ssh-agent e, infine, disattivazione sicura del login via password lato server.Generare la coppia di chiavi con ssh-keygenIl primo passo è la scelta dell’algoritmo. Nel 2026 la raccomandazione per la quasi totalità degli scenari è Ed25519: chiavi più corte di RSA, generazione e verifica più veloci, sicurezza equivalente (o superiore) a RSA 3072/4096 bit. OpenSSH genera Ed25519 come default da ssh-keygen 9.5 (fine 2023), ma vale la pena specificarlo esplicitamente per chiarezza e portabilità degli script:ssh-keygen -t ed25519 -C "nome@host-o-scopo-della-chiave"Il comando chiede dove salvare la chiave (default ~/.ssh/id_ed25519) e una passphrase. Imposta sempre una passphrase: senza, chiunque copi il file della chiave privata (backup non cifrato, laptop rubato, snapshot di VM) ottiene accesso diretto ai sistemi target. Se devi supportare dispositivi legacy che non gestiscono Ed25519 (raro, ma capita con apparati di rete datati), usa RSA a 4096 bit come alternativa:ssh-keygen -t rsa -b 4096 -C "nome@host-o-scopo-della-chiave"Un’opzione spesso sottovalutata è l’uso di chiavi FIDO2/hardware, dove il materiale crittografico non lascia mai una security key fisica (es. YubiKey):ssh-keygen -t ed25519-sk -C "chiave-hardware"Per ambienti con requisiti di compliance elevati o accessi amministrativi privilegiati, vale la pena valutarla: anche in caso di compromissione totale della workstation, la chiave privata resta inaccessibile senza il dispositivo fisico.Distribuire la chiave pubblicaIl modo più rapido è ssh-copy-id, che si occupa di creare (se assente) la directory ~/.ssh sul server remoto, con permessi corretti, e di appendere la chiave pubblica a authorized_keys:ssh-copy-id -i ~/.ssh/id_ed25519.pub utente@serverSe ssh-copy-id non è disponibile (ad esempio da un client Windows senza WSL), il metodo manuale equivalente è:cat ~/.ssh/id_ed25519.pub | ssh utente@server \ "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"I permessi contano davvero: OpenSSH lato server rifiuta silenziosamente authorized_keys se la directory .ssh è scrivibile da altri utenti o se il file ha permessi troppo aperti. Se il login a chiave “non funziona” senza errori evidenti, controlla sempre chmod 700 ~/.ssh e chmod 600 ~/.ssh/authorized_keys prima di cercare altrove.Gestire host multipli con ~/.ssh/configChi amministra decine di server trae grande beneficio da un file di configurazione client centralizzato. Invece di ricordare chiave, utente e porta per ogni host, definisci alias in ~/.ssh/config:Host prod-web01 HostName 203.0.113.10 User deploy Port 2222 IdentityFile ~/.ssh/id_ed25519_prod IdentitiesOnly yes Host *.interno.lan User admin IdentityFile ~/.ssh/id_ed25519_lan ForwardAgent noDa quel momento ssh prod-web01 basta e avanza. L’opzione IdentitiesOnly yes è importante quando gestisci più chiavi: senza di essa, il client SSH può offrire al server tutte le identità disponibili nell’agent, esaurendo il numero massimo di tentativi consentiti (MaxAuthTries) prima di arrivare a quella corretta.ssh-agent: passphrase una sola volta per sessioneCon una passphrase impostata (come dovrebbe essere sempre), digitarla a ogni connessione è scomodo. ssh-agent mantiene la chiave decifrata in memoria per la durata della sessione:eval "$(ssh-agent -s)" ssh-add ~/.ssh/id_ed25519Sulla maggior parte delle distribuzioni desktop l’agent è già integrato con il session manager. Evita ForwardAgent yes indiscriminato: l’agent forwarding espone la tua chiave in memoria a qualunque processo con privilegi root sul server intermedio, un rischio concreto se quel server non è pienamente fidato. Se ti serve saltare attraverso un bastion host, preferisci ProxyJump:Host bastion HostName bastion.example.com User jump Host target-interno HostName 10.0.5.20 User admin ProxyJump bastionDisabilitare l’autenticazione a password lato serverSolo dopo aver verificato che il login a chiave funziona correttamente (testalo in una sessione separata prima di chiudere quella attuale), disattiva la password lato server. Sulle distribuzioni moderne (Debian/Ubuntu recenti), il modo più pulito è un drop-in dedicato, che viene caricato prima del file principale e quindi vince sui default:sudo mkdir -p /etc/ssh/sshd_config.d sudo tee /etc/ssh/sshd_config.d/00-disable-password-auth.conf <<'EOF' PasswordAuthentication no KbdInteractiveAuthentication no PermitRootLogin prohibit-password EOF sudo sshd -t && sudo systemctl reload sshdsshd -t valida la sintassi prima del reload: un errore di battitura in questo file può tagliarti fuori dal server se non hai un accesso alternativo (console cloud, iDRAC/iLO, ecc.). PermitRootLogin prohibit-password è la scelta consigliata rispetto a no secco: mantiene comunque disponibile il root via chiave per operazioni di emergenza, ma blocca il tentativo via password.Checklist finale per un hardening solidoUna chiave dedicata per servizio/scopo (deploy, amministrazione, CI/CD), non un’unica chiave riutilizzata ovunque.Passphrase sempre presente sulle chiavi memorizzate su disco non cifrato.Audit periodico di authorized_keys su ogni server: rimuovi le chiavi di chi ha lasciato il team o non necessita più di accesso.AuthorizedKeysCommand con backend centralizzato (Vault, LDAP) se gestisci decine di server e vuoi evitare la distribuzione manuale delle chiavi.Fail2ban o equivalente comunque attivo, come difesa in profondità anche a password disabilitate.ConclusioneIl passaggio da password a chiavi SSH richiede pochi minuti per server, ma elimina una delle superfici di attacco più sfruttate contro sistemi Linux esposti. La combinazione di Ed25519, ~/.ssh/config ben strutturato e password disabilitate lato server è oggi lo standard minimo per qualunque infrastruttura, piccola o grande che sia.Fonte: LinuxBlog.io.
  • 0 Votazioni
    1 Post
    0 Visualizzazioni
    blog@spcnet.itB
    Il problema non è la mancanza di strumenti, è l’ordine in cui si usanoWindows include più utility diagnostiche di quante un amministratore ne userà mai tutte. Eppure la causa più comune di sessioni di troubleshooting infruttuose non è l’ignoranza dei tool, ma la sequenza sbagliata: si parte da un comando di riparazione (sfc /scannow, un reset di Windows Update, un DISM al buio) prima ancora di aver capito quale sottosistema sta effettivamente fallendo. Il risultato è tempo perso, evidenze diagnostiche distrutte dal riavvio, e spesso la causa radice che resta lì, pronta a ripresentarsi la settimana successiva.Vale la pena fermarsi a formalizzare un metodo, perché è quello che separa un troubleshooting efficace da un’accozzaglia di tentativi casuali. Di seguito un processo in cinque passi, seguito da una rassegna degli strumenti chiave e da una tabella sintesi sintomo → strumento che può diventare un riferimento rapido da tenere a portata di mano durante un incidente.Un processo ripetibile prima di toccare qualsiasi comandoLa maggior parte delle sessioni di troubleshooting falliscono prima ancora che venga lanciato il primo comando. Un amministratore vede un errore, prova un comando di riparazione che conosce, riavvia, e scopre che il problema originale è ancora lì. Un approccio più solido richiede di rallentare abbastanza da stabilire una baseline:Confermare o riprodurre il problema: è cronico o è stato un episodio isolato?Registrare il sintomo esatto: messaggio di errore, orario, utente coinvolto, dispositivo, modifiche recenti.Raccogliere le evidenze dal sistema più probabilmente coinvolto.Applicare una modifica alla volta, partendo dall’opzione meno invasiva.Verificare il risultato e documentare cosa è effettivamente cambiato.Un esempio concreto: se Windows Update fallisce con un errore generico, la tentazione è resettare tutti i componenti di aggiornamento in blocco. Il primo passo corretto è invece capire in quale fase è avvenuto il fallimento — scan, download, staging, installazione o riavvio — perché questa distinzione determina se bisogna guardare i log di Windows Update, i log di servicing, lo stato del disco, la configurazione delle policy o la connettività di rete.Event Viewer: il primo posto dove cercare quando c’è un timestampEvent Viewer è il punto di partenza quando il sintomo ha un orario preciso: un crash applicativo, un riavvio inatteso, un servizio che si ferma, un problema di driver, un’installazione fallita. Si parte dai Windows Logs, filtrando Application, System e Setup per eventi Critical, Error e Warning nell’intorno temporale del problema, per poi individuare l’event source, l’event ID, il modulo che genera il fault, il nome del servizio o del driver coinvolto.Il criterio per separare il segnale dal rumore è la ripetibilità: un warning isolato di ieri è quasi sempre rumore; un errore che compare sistematicamente ogni volta che si apre una determinata applicazione è un segnale affidabile. Le evidenze diagnostiche più utili sono quelle correlate nel tempo e riproducibili, non gli eventi isolati.SFC prima, DISM solo se SFC non bastaSystem File Checker (SFC) è uno strumento di riparazione mirato per i file di sistema protetti. Si usa quando una feature nativa di Windows si comporta in modo anomalo, un componente integrato non parte, oppure Event Viewer punta a file del sistema operativo mancanti o corrotti:sfc /scannowSFC è utile perché verifica e sostituisce i file protetti senza richiedere una reinstallazione, ma dipende dal component store locale come sorgente di riparazione. Se quello store è danneggiato, SFC può segnalare corruzione trovata ma non riparabile del tutto. A quel punto il passo successivo è DISM, non ripetere SFC all’infinito sperando in un risultato diverso.Deployment Image Servicing and Management (DISM) opera a livello di image e component store, uno strato sotto SFC. Va usato quando SFC non riesce a completare le riparazioni, quando l’installazione di Windows Update o di una feature fallisce ripetutamente, o quando il problema è a livello di servicing. Il comando di riparazione online più comune:DISM /Online /Cleanup-Image /RestoreHealthIn ambienti enterprise, DISM può aver bisogno di una sorgente di riparazione affidabile — supporto di installazione, un’immagine montata, o una posizione di contenuto gestita — soprattutto quando gli endpoint non possono scaricare i contenuti di riparazione da Windows Update. Dopo che DISM completa con successo, conviene rilanciare SFC, così i file protetti possono essere riparati da un component store ormai sano.Windows Update: capire in quale fase fallisce prima di resettare tuttoIl troubleshooting di Windows Update deve partire dall’identificazione della fase fallita. Un fallimento nello scan suggerisce problemi di policy, rete, proxy o sorgente di aggiornamento. Un fallimento nel download indica problemi di connettività, disponibilità dei contenuti o cache. Un fallimento nell’installazione punta spesso allo servicing stack, al component store, allo spazio su disco, a un riavvio pendente o a un driver in conflitto.Sulle versioni moderne di Windows, Windows Update si basa su dati Event Tracing for Windows (ETW) piuttosto che scrivere un semplice log testuale in continuo. Per generare un log leggibile quando serve un dettaglio più approfondito lato client, si usa PowerShell:Get-WindowsUpdateLogVale anche controllare Event Viewer nei log operativi del client di Windows Update e il Setup log per gli eventi di installazione. Se lo stesso pacchetto KB fallisce ripetutamente, conviene verificare se l’aggiornamento è applicabile, se esiste un aggiornamento che lo sostituisce, e da quale sorgente il dispositivo riceve gli update — Windows Update diretto, Microsoft Update, WSUS, oppure una piattaforma di gestione come Intune o Configuration Manager.Un reset completo di Windows Update dovrebbe essere un passo tardivo, non il primo. Resettare i servizi e svuotare le cache può sbloccare client incastrati, ma distrugge anche evidenze utili. Meglio catturare prima il codice di errore, i log e la cronologia degli aggiornamenti.“La rete non funziona” è quasi sempre DNS o configurazioneI sintomi di rete richiedono un punto di partenza diverso, perché gli utenti spesso descrivono come “la rete è giù” un problema che in realtà è DNS, routing, autenticazione, policy del firewall o un singolo endpoint applicativo che non risponde. È corretto partire dalla configurazione TCP/IP locale prima di testare i servizi remoti.Un errore comune tra amministratori meno esperti è dare per scontato che “il ping non risponde” equivalga a “la rete è giù”. In ambienti enterprise questa assunzione è spesso sbagliata: molti sistemi sono configurati per ignorare le richieste ICMP pur continuando a erogare regolarmente il servizio previsto. Un firewall può bloccare ICMP, una policy di sicurezza può disabilitare le risposte, un servizio cloud può non rispondere mai al ping. La domanda giusta non è se un dispositivo risponde al ping, ma se il servizio richiesto è effettivamente raggiungibile: bisogna sempre testare ciò che l’utente sta effettivamente cercando di usare, con strumenti come ipconfig, nslookup e tracert mirati sul servizio specifico.Tabella di riferimento rapido: sintomo → strumentoSintomoPartire daPerchéApp che va in crash o si chiude inaspettatamenteEvent Viewer, poi Reliability MonitorIdentifica moduli in fault, errori applicativi e pattern di modifiche recentiWindows Update fallisce ripetutamenteLog di Windows Update, Setup log, DISMSepara i fallimenti di scan, download, installazione e servicingFeature di Windows mancanti o instabiliSFC, poi DISM se SFC non riparaRipara i file di sistema protetti e il component store sottostanteUtenti non raggiungono risorse di reteipconfig, ping, nslookup, tracertValida configurazione locale, raggiungibilità, DNS e routing in ordineLe performance degradano improvvisamenteTask Manager, Resource Monitor, Event ViewerCorrela la pressione sulle risorse con servizi, driver ed erroriReliability Monitor merita una menzione a parte perché offre una vista a timeline di crash applicativi, fallimenti di Windows, installazioni di driver ed eventi di aggiornamento. È meno dettagliato di Event Viewer, ma resta eccellente per individuare rapidamente cosa è cambiato immediatamente prima che iniziasse un problema ricorrente.Costruire il proprio toolkit di troubleshootingPer un professionista IT, l’abilità di troubleshooting più preziosa non è memorizzare comandi, ma sapere quale fonte di evidenza fidarsi per una determinata classe di problema. Event Viewer dice cosa Windows ha registrato; Reliability Monitor mostra quando i problemi sono iniziati. Una checklist pratica da seguire durante un incidente:Registrare sintomi esatti, orario, dispositivo, utente e modifiche recenti.Controllare i log più rilevanti prima di applicare riparazioni ad ampio raggio.Eseguire i comandi di riparazione da un terminale elevato e catturarne l’output.Cambiare una variabile alla volta, per sapere con certezza cosa ha risolto il problema.Verificare dal punto di vista dell’utente, non solo dalla console amministrativa.Questa disciplina previene due errori tipici: eseguire riparazioni distruttive troppo presto, e dichiarare vittoria prima di aver verificato il flusso di lavoro reale. Se un utente non riesce ad aprire una condivisione di rete, un ping riuscito non è il traguardo: il traguardo è l’utente che apre la condivisione, accede ai file attesi e conferma che il problema non si ripresenta.ConclusioneLa differenza tra una sessione di troubleshooting produttiva e una frustrante raramente sta nella conoscenza di comandi avanzati. Sta nel partire dal sintomo invece che dal comando, chiedersi quale evidenza confermerebbe o smentirebbe la causa più probabile, e solo a quel punto scegliere lo strumento che fornisce quell’evidenza nel modo più veloce. È questa disciplina che trasforma una collezione di utility in un vero toolkit diagnostico.Fonte: Critical Windows Troubleshooting Tools: Stop Wasting Time on the Wrong Fixes, Petri IT Knowledgebase
  • 0 Votazioni
    1 Post
    0 Visualizzazioni
    blog@spcnet.itB
    Da anni gli sviluppatori C# aspettano un modo nativo per dire “questo valore è esattamente uno tra questi tipi, e nient’altro”, con il compilatore in grado di garantirlo. In assenza di un supporto di linguaggio, la community si è arrangiata con pattern come Results<T> di ASP.NET Core Minimal API o con librerie come OneOf. Funzionano, ma con un limite strutturale: se aggiungi un quarto caso possibile a una funzione che prima ne restituiva tre, nessuno ti avvisa che uno switch a valle non gestisce il nuovo tipo. Manca l’esaustività, che è poi il punto centrale delle discriminated union.Con .NET 11 Preview 6 (rilasciata il 14 luglio 2026) e C# 15, questa lacuna si chiude: arriva la parola chiave union, insieme a un intero pacchetto di funzionalità correlate (conversioni implicite, pattern matching esaustivo, gestione della nullabilità) che rendono i union type un cittadino di prima classe del linguaggio.La sintassi: dichiarare un union typeLa forma più semplice è la union declaration, una sintassi compatta che genera automaticamente uno struct:public union Pet(Cat, Dog, Bird);Questa singola riga dice al compilatore che un Pet è esattamente un Cat, un Dog o un Bird, e nient’altro. Sotto il cofano, il compilatore genera uno struct che implementa l’interfaccia System.Runtime.CompilerServices.IUnion e conserva il valore effettivo in una proprietà Value di tipo object?.I union generici sono immediatamente utili per modellare risultati di operazioni che possono fallire, un caso d’uso ricorrentissimo in codice di produzione:public union Result<TSuccess, TError>(TSuccess, TError); Result<User, Error> Register(string username) { if (string.IsNullOrEmpty(username)) return new Error("Username cannot be empty"); return new User(username); }Da notare l’ultima riga: nessun wrapping esplicito, nessuna chiamata a un factory method. Il valore User o Error viene convertito implicitamente in Result<User, Error> grazie alle union conversion generate automaticamente per ogni case type.Pattern matching esaustivo, finalmenteIl vero salto di qualità è nel matching. Se dimentichi un caso in uno switch su un union type, il compilatore te lo dice:string Describe(Pet pet) => pet switch { Dog d => d.Name, Cat c => c.Name, // CS8509: switch expression does not handle all // possible values of its input type (Bird) };Aggiungendo il caso mancante, l’avviso scompare, e non serve più il classico _ => throw new InvalidOperationException("unreachable") per zittire il compilatore:string Describe(Pet pet) => pet switch { Dog d => d.Name, Cat c => c.Name, Bird b => b.Name, };Il punto interessante è che questa esaustività è dinamica: se in futuro aggiungi un nuovo case type al union (per esempio un quarto animale), ogni switch esistente che non lo gestisce si illumina di un warning. Per chi ha inseguito bug di produzione causati da un case dimenticato in un evento di dominio, è un cambiamento non da poco.I pattern si applicano direttamente al union, senza bisogno di accedere manualmente a .Value: il compilatore effettua l’unwrapping in automatico, anche negli if pattern classici:if (pet is Dog d) { Console.WriteLine(d.Name); }Gestione del nullIl valore di default di un union type ha Value == null, ed è possibile intercettarlo esplicitamente con il pattern null:string Describe(Pet pet) => pet switch { null => "nessun animale", Dog d => d.Name, Cat c => c.Name, Bird b => b.Name, };La necessità o meno del ramo null dipende dal fatto che il parametro o il campo union-typed sia nullable: l’analisi di nullabilità del compilatore guida correttamente questi casi, in coerenza con le annotazioni #nullable enable già in uso nella maggior parte delle codebase moderne.Un caso pratico: modellare eventi di dominioI union type diventano davvero interessanti quando li si combina con i record per il domain modeling, per esempio in un sistema di elaborazione ordini con eventi distinti:public record OrderPlaced(Guid OrderId, decimal Total); public record OrderShipped(Guid OrderId, string TrackingNumber); public record OrderCancelled(Guid OrderId, string Reason); public union OrderEvent(OrderPlaced, OrderShipped, OrderCancelled); string Summarize(OrderEvent evt) => evt switch { OrderPlaced p => $"Ordine {p.OrderId} piazzato per {p.Total:C}", OrderShipped s => $"Ordine {s.OrderId} spedito, tracking: {s.TrackingNumber}", OrderCancelled c => $"Ordine {c.OrderId} annullato: {c.Reason}", };Quando tra tre mesi qualcuno aggiungerà OrderRefunded al union, ogni handler che non lo gestisce lancerà un warning in fase di compilazione, invece di fallire silenziosamente in produzione. È il compilatore che fa da revisore di esaustività al posto tuo.I union possono anche esporre metodi e proprietà calcolate (ma non campi d’istanza), utile per incapsulare logica di conversione:public union Length(Meters, Feet) { public double TotalMeters => this switch { Meters m => m.Value, Feet f => f.Value * 0.3048, _ => throw new InvalidOperationException(), }; }Union personalizzati con l’attributo [Union]La parola chiave union genera sempre uno struct. Se per motivi di identità, ereditarietà o layout di memoria serve un tipo reference, è possibile costruire un union personalizzato applicando direttamente l’attributo System.Runtime.CompilerServices.UnionAttribute e implementando l’interfaccia IUnion:[System.Runtime.CompilerServices.Union] public class Shape : System.Runtime.CompilerServices.IUnion { private readonly object? _value; public Shape(Circle value) { _value = value; } public Shape(Rectangle value) { _value = value; } public object? Value => _value; }Nella grande maggioranza dei casi, però, la sintassi union compatta copre già ogni esigenza pratica: l’approccio con attributo è pensato per scenari con requisiti specifici che lo struct generato non può soddisfare.Come provarlo oggiI union type sono attualmente in preview. Per sperimentarli serve l’SDK .NET 11 Preview e questa configurazione nel file di progetto:<PropertyGroup> <LangVersion>preview</LangVersion> <TargetFramework>net11.0</TargetFramework> </PropertyGroup>Vale la pena ricordare che si tratta di una feature specification ancora in evoluzione: alcuni dettagli di comportamento (per esempio le regole esatte su nullabilità di default o sulle conversioni sollevate/”lifted”) sono ancora oggetto di discussione nel repository dotnet/csharplang, quindi è normale osservare piccoli cambiamenti tra una preview e l’altra prima del rilascio finale.ConclusioniF# ha le discriminated union fin dalle origini, e la richiesta di un equivalente in C# (csharplang issue #113) è aperta da anni. Con l’arrivo dei union type, non ogni problema di modellazione richiede più una gerarchia di classi: per rappresentare “uno tra un insieme chiuso di tipi”, ora esiste un costrutto di linguaggio dedicato, con conversioni implicite, pattern matching esaustivo e un’ottima integrazione con i record esistenti. Per chi lavora ogni giorno con API che possono restituire risultati eterogenei, o con event sourcing e domain modeling, è una delle novità più concrete della prossima versione di C#.Fonte: .NET Blog, C# language reference proposal: Unions e Maarten Balliauw.
  • 0 Votazioni
    1 Post
    0 Visualizzazioni
    blog@spcnet.itB
    Perché ogni server esposto a Internet ha bisogno di Fail2banBasta controllare i log di autenticazione di un qualunque server Linux raggiungibile da Internet per rendersi conto di un fatto scomodo: nel giro di poche ore compaiono centinaia di tentativi di accesso falliti su SSH, pannelli web o form di login. Non è un attacco mirato: sono scanner automatici che perlustrano di continuo intere sottoreti, alla ricerca di credenziali deboli o servizi mal configurati. Ignorare questo rumore di fondo non è un’opzione, ma bloccare manualmente ogni IP sospetto è impraticabile.Fail2ban risolve il problema analizzando i log in tempo reale e bannando automaticamente, tramite il firewall, gli indirizzi IP che superano una soglia di tentativi falliti in una finestra temporale configurabile. È uno strumento maturo, leggero, presente nei repository di tutte le principali distribuzioni, ma la configurazione di default lascia molto sul tavolo: un bantime di 10 minuti, tanto per fare un esempio, è quasi inutile contro un attaccante automatizzato che può semplicemente aspettare e riprovare.In questa guida vediamo come installare, configurare e soprattutto tunare Fail2ban per ottenere una protezione reale, con particolare attenzione agli scenari più comuni su un server di produzione: SSH, Nginx, firewall moderni basati su nftables e persistenza dei ban tra un reboot e l’altro.I tre concetti chiave: filter, jail, actionPrima di mettere mano alla configurazione conviene avere chiaro il modello concettuale di Fail2ban, perché tutta la configurazione ruota attorno a tre elementi:Filter: un insieme di espressioni regolari che individuano le righe di log corrispondenti a un tentativo di accesso fallito.Jail: combina un filtro con il percorso del log da monitorare, le soglie di attivazione e l’azione da eseguire al superamento della soglia.Action: cosa succede quando la soglia viene superata. Nella maggior parte dei casi è una regola firewall, ma può includere anche l’invio di una notifica via email.Fail2ban include già filtri e jail pronti per decine di servizi (SSH, Apache, Nginx, Postfix, Dovecot…). Nella pratica quotidiana ci si limita ad abilitare le jail utili e a regolare qualche parametro.InstallazioneFail2ban è disponibile nei repository ufficiali di tutte le distribuzioni principali.Debian/Ubuntu:sudo apt update sudo apt install fail2banFedora / RHEL 9+ / Rocky / AlmaLinux:sudo dnf install fail2banArch Linux:sudo pacman -S fail2banAbilitiamo e avviamo il servizio, poi verifichiamo lo stato:sudo systemctl enable --now fail2ban sudo systemctl status fail2banSe lo stato non riporta active (running), i log vanno controllati con sudo journalctl -u fail2ban -n 50.Configurare Fail2ban nel modo correttoUn errore comune è modificare direttamente /etc/fail2ban/jail.conf: questo file viene sovrascritto a ogni aggiornamento del pacchetto, con conseguente perdita delle personalizzazioni. L’approccio corretto è creare un file dedicato dentro jail.d/:sudo nano /etc/fail2ban/jail.d/custom.confIn alternativa si può copiare il file di default in jail.local, che ha priorità sui valori in jail.conf:sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.localLa sezione [DEFAULT]Nella sezione [DEFAULT] si impostano i valori applicati a tutte le jail, salvo override specifico:[DEFAULT] bantime = 1h findtime = 10m maxretry = 5 ignoreip = 127.0.0.1/8 ::1bantime: durata del ban. Il default (spesso 10 minuti) è troppo permissivo: 1 ora è un buon punto di partenza, e per attaccanti persistenti si può salire a 24h o 1w. Il valore -1 produce un ban permanente, da usare con cautela.findtime: la finestra temporale in cui vengono contati i fallimenti.maxretry: numero di tentativi falliti prima del ban. 5 è ragionevole per SSH, si può scendere a 3 per una postura più aggressiva.ignoreip: gli IP che non verranno mai bannati. È fondamentale aggiungere qui il proprio IP prima di abilitare qualsiasi jail: restare fuori dal proprio server per un ban accidentale è un classico errore da evitare.Se il server ha un indirizzo IPv6 pubblico, va incluso anche quello: alcuni filtri più datati intercettano solo IPv4, quindi conviene verificare che le jail catturino correttamente entrambi i protocolli.La jail SSHÈ la jail più importante per la maggior parte dei server. In jail.local o in un nuovo file /etc/fail2ban/jail.d/sshd.conf:[sshd] enabled = true port = ssh logpath = %(sshd_log)s backend = %(sshd_backend)s maxretry = 3 bantime = 1hSe SSH è stato spostato su una porta non standard (buona pratica consigliata), va aggiornata la riga port. Sui sistemi basati su systemd, %(sshd_log)s punta automaticamente al journal; sui sistemi più datati che usano /var/log/auth.log o /var/log/secure, Fail2ban gestisce la differenza tramite il parametro backend. Dopo ogni modifica alla configurazione:sudo fail2ban-client reloadJail per NginxI server web attirano un tipo diverso di abuso: scanner di URL 404, bruteforcer su form di login, bot che generano richieste inutili.[nginx-http-auth] enabled = true logpath = %(nginx_error_log)s maxretry = 3 [nginx-limit-req] enabled = true logpath = %(nginx_error_log)s maxretry = 10La jail nginx-limit-req intercetta i client che superano i limit_req configurati in Nginx: è una combinazione efficace se il server web è già stato ottimizzato per gestire traffico elevato. Se Fail2ban segnala che un percorso di log non esiste, va impostato esplicitamente, ad esempio logpath = /var/log/nginx/error.log.Verificare jail e ban attiviIl comando fail2ban-client è lo strumento principale per monitorare la situazione. Elenco delle jail attive:sudo fail2ban-client statusDettaglio di una jail specifica, comprensivo di IP attualmente bannati:sudo fail2ban-client status sshdPer bannare o sbannare manualmente un IP:sudo fail2ban-client set sshd banip 203.0.113.99 sudo fail2ban-client set sshd unbanip 203.0.113.99Il comando unbanip è quello da tenere a portata di mano nel caso in cui ci si banni da soli per errore, prima di aver aggiunto il proprio IP a ignoreip.Ban incrementali con la jail recidiveUna delle funzionalità meno conosciute ma più efficaci di Fail2ban è la jail recidive, che monitora il log interno di Fail2ban stesso e applica ban molto più lunghi agli IP che, dopo la scadenza di un primo ban, tornano a fare bruteforcing.[recidive] enabled = true logpath = /var/log/fail2ban.log action = %(action_mwl)s bantime = 1w findtime = 1d maxretry = 5Con questa configurazione, un IP bannato 5 volte in un giorno riceve un ban di una settimana: è l’equivalente più vicino a una blocklist persistente senza dover integrare feed di threat intelligence esterni. Su sistemi che scrivono solo sul journal, va impostato backend = systemd nella jail recidive, oppure va verificato che Fail2ban stia scrivendo un log tradizionale.Testare i filtri prima di attivarliPrima di abilitare una jail, conviene verificare che il regex del filtro corrisponda davvero alle righe di log presenti sul sistema:sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.confL’output riporta gli IP individuati e il numero di righe che hanno fatto match. Un filtro che non intercetta nulla non protegge nulla: questo comando è indispensabile soprattutto quando si scrive un filtro personalizzato per un’applicazione custom, dentro /etc/fail2ban/filter.d/:# /etc/fail2ban/filter.d/myapp-auth.conf [Definition] failregex = ^<HOST> .* "POST /login" 401 ignoreregex =Il tag <HOST> è obbligatorio: Fail2ban lo sostituisce con un’espressione regolare che cattura l’indirizzo IP da bannare. Un pattern troppo generico rischia di bannare traffico legittimo, quindi va sempre validato con fail2ban-regex prima di collegarlo a una jail attiva.nftables, firewalld e persistenza dei banSu Debian 12+ e Ubuntu 22.04+, nftables è il backend firewall di default. L’azione di ban predefinita di Fail2ban usa ancora iptables, che nella maggior parte delle installazioni funziona tramite il layer di compatibilità iptables-nft. Se invece si usa nftables puro, l’azione va impostata esplicitamente:banaction = nftables-multiport banaction_allports = nftables-allportsSu RHEL, Fedora e Rocky, dove firewalld è lo standard, va usata l’azione corrispondente:banaction = firewallcmd-rich-rules banaction_allports = firewallcmd-allportsPer default, i ban sono mantenuti in memoria e vengono persi a ogni riavvio. Per farli sopravvivere ai reboot va abilitato il database SQLite (su molte distribuzioni recenti è già attivo di default):dbfile = /var/lib/fail2ban/fail2ban.sqlite3 dbpurgeage = 7dUna configurazione di partenza completaEcco un file /etc/fail2ban/jail.d/custom.conf che copre i casi d’uso più comuni su un server Linux tipico, da usare come punto di partenza:[DEFAULT] bantime = 2h findtime = 10m maxretry = 5 ignoreip = 127.0.0.1/8 ::1 dbfile = /var/lib/fail2ban/fail2ban.sqlite3 dbpurgeage = 7d [sshd] enabled = true port = ssh logpath = %(sshd_log)s backend = %(sshd_backend)s maxretry = 3 bantime = 6h [nginx-http-auth] enabled = true logpath = %(nginx_error_log)s maxretry = 4 [nginx-limit-req] enabled = true logpath = %(nginx_error_log)s maxretry = 10 [recidive] enabled = true logpath = /var/log/fail2ban.log bantime = 1w findtime = 1d maxretry = 5sudo fail2ban-client reload sudo fail2ban-client statusCosa Fail2ban non risolveFail2ban è uno strumento reattivo, non preventivo: banna un IP solo dopo che ha già effettuato diversi tentativi. Non copre, da solo, alcuni scenari:attacchi bruteforce distribuiti su migliaia di IP diversi, ciascuno con uno o due tentativi soltanto;exploit zero-day che non generano righe di log riconoscibili;attacchi a livello applicativo che non producono un fallimento di autenticazione tracciabile.Per una protezione a più livelli, Fail2ban va affiancato all’autenticazione SSH tramite chiavi (disabilitando del tutto l’autenticazione via password), a un firewall configurato correttamente e a una revisione periodica dei log. Un’attenzione particolare va riservata ai server dietro Cloudflare o un altro reverse proxy: senza ripristinare l’IP originale del visitatore (tramite mod_remoteip su Apache o real_ip_module su Nginx), Fail2ban finirebbe per bannare gli IP del proxy stesso invece degli attaccanti reali.Comandi da tenere sempre a portata di manosudo fail2ban-client status — elenco di tutte le jail attivesudo fail2ban-client status sshd — stato dettagliato di una jailsudo fail2ban-client set sshd banip 1.2.3.4 — ban manuale di un IPsudo fail2ban-client set sshd unbanip 1.2.3.4 — rimozione manuale di un bansudo fail2ban-client reload — ricarica la configurazione dopo una modificasudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf — test di un filtrosudo tail -f /var/log/fail2ban.log — monitoraggio dei ban in tempo realeConclusioneFail2ban resta uno degli strumenti che meritano un posto fisso su ogni server Linux esposto a Internet: l’installazione richiede pochi minuti e già con una configurazione minima riduce in modo drastico il rumore generato da scanner SSH e probe automatizzati sui servizi web. La differenza reale, però, la fanno tre accorgimenti spesso trascurati: impostare un bantime ragionevole (il default di 10 minuti è quasi inutile), aggiungere sempre il proprio IP a ignoreip prima di abilitare le jail, e attivare la jail recidive per penalizzare chi insiste. Da soli, questi tre passaggi fanno la differenza tra un’installazione di default e una protezione che funziona davvero.Fonte: Fail2ban on Linux: Protect Your Server from Brute-Force Attacks, LinuxBlog.io
  • 0 Votazioni
    1 Post
    0 Visualizzazioni
    blog@spcnet.itB
    Perché il tuo server usa swap con RAM libera (e come scoprire chi è il colpevole con smem)Capita spesso: un server ha 32 o 64 GB di RAM, il carico è tutto sommato modesto, eppure free -h mostra qualche centinaio di MB o addirittura qualche GB in swap. Il riflesso istintivo di molti sistemisti è colpevolizzare la RAM insufficiente e chiedere un upgrade. Nella maggior parte dei casi, però, il problema non è la quantità di memoria disponibile, ma quali processi stanno finendo in swap e perché. Per rispondere serve uno strumento che guardi dentro ai singoli processi, non solo ai numeri aggregati: smem.Perché Linux usa lo swap anche con RAM liberaIl kernel Linux non tratta la RAM come una risorsa da tenere il più vuota possibile: la usa aggressivamente per la page cache, per velocizzare I/O su file e librerie. Quando il kernel individua pagine di memoria che non vengono acquisite/toccate da tempo, può decidere di spostarle in swap per liberare RAM fisica da destinare alla cache, anche se tecnicamente c’è ancora memoria “libera” disponibile. Questo comportamento è regolato dal parametro vm.swappiness (0-100, con default storicamente a 60 su molte distribuzioni), che indica al kernel quanto è propenso a scambiare memoria anonima verso lo swap piuttosto che liberare pagine di cache.Il punto chiave: prima di toccare vm.swappiness alla cieca, bisogna sapere chi sta effettivamente occupando swap. Un valore aggregato come quello di free non lo dice. Serve la vista per processo.smem: memoria proporzionale, non solo RSSTool classici come top o ps mostrano RSS (Resident Set Size), che però ha un difetto noto: se due processi condividono le stesse pagine di memoria (librerie condivise, memoria mappata), quella memoria viene contata per intero in ognuno dei due, gonfiando artificialmente i numeri quando si sommano i processi.smem risolve il problema calcolando anche:USS (Unique Set Size): memoria usata esclusivamente da quel processo, non condivisa con nessun altro — utile per capire quanto libereresti davvero uccidendo il processoPSS (Proportional Set Size): memoria condivisa divisa proporzionalmente tra i processi che la usano — la metrica più corretta per sommare l’uso reale di memoria di un sistema senza doppi conteggiSwap: quanta memoria di quello specifico processo è stata spostata su discoInstallazionesmem non è quasi mai preinstallato, ma è nei repository di tutte le principali distribuzioni:# RHEL / CentOS / AlmaLinux / Fedora dnf install smem # Debian / Ubuntu apt install smemUso pratico: trovare chi consuma swapIl comando base per ordinare i processi per swap consumato:smem -rs swapOutput tipico (troncato):PID User Command Swap USS PSS RSS 28986 mysql /usr/sbin/mysqld --daemon 476372 10963864 10963932 10965112 29152 root /usr/sbin/rsyslogd -n 371424 3956 17475 43352 31423 root /opt/fluent-bit/bin/fluent 22508 26612 26739 29100Da un output così è immediato capire che mysqld e rsyslogd sono i principali responsabili dell’uso di swap su questo host, e non un generico “poca RAM”. Da qui l’indagine si sposta su quel servizio specifico: per MySQL, ad esempio, tipicamente significa rivedere innodb_buffer_pool_size rispetto alla RAM totale disponibile, o verificare connessioni/thread che allocano memoria inutilmente.Alcune varianti utili del comando:# Ordina per USS (memoria realmente esclusiva del processo) smem -rs uss # Filtra per utente smem -u # Vista grafica a torta per RSS (richiede matplotlib) smem --pie name -s rssDalla diagnosi al tuningUna volta identificati i servizi che finiscono in swap, ci sono due strade complementari:Agire sul servizio: ridimensionare i buffer/pool applicativi (buffer pool di MySQL, heap JVM, cache applicative) in base alla RAM effettivamente disponibile, invece di lasciare valori di default pensati per macchine generiche.Agire sul kernel, solo dopo aver capito il quadro reale: ridurre vm.swappiness per rendere il kernel meno aggressivo nello spostare memoria anonima in swap:sysctl vm.swappiness=1 echo 'vm.swappiness=1' >> /etc/sysctl.confDa notare che vm.swappiness=0 non disabilita completamente lo swap su kernel recenti (dal 3.5 in poi il comportamento è cambiato rispetto alle versioni più vecchie), mentre valori molto bassi come 1 riducono drasticamente la propensione allo swap mantenendo comunque una valvola di sicurezza in caso di pressione di memoria reale. Su un database server dedicato, dove si preferisce quasi sempre tenere i dati “caldi” in RAM piuttosto che liberare cache, è una delle prime ottimizzazioni da considerare.ConclusioneVedere swap attivo su un server con RAM apparentemente libera non è di per sé un allarme: è il comportamento normale di un kernel che ottimizza l’uso della cache. Il problema comincia quando lo swap coinvolge processi critici per la latenza, come un database o un servizio applicativo, degradando le performance in modo silenzioso. smem -rs swap è il primo comando da lanciare in questi casi: in pochi secondi isola il processo responsabile, distingue la memoria condivisa da quella esclusiva, e trasforma un sintomo generico (“il server è lento”) in un’azione concreta di tuning, sul servizio o sul kernel.Fonte: LinuxBlog.io, “Diagnosing Swap Usage with smem on Linux”.
  • 0 Votazioni
    1 Post
    0 Visualizzazioni
    blog@spcnet.itB
    Chi sta integrando agenti AI in pipeline CI/CD si scontra presto con un problema pratico: come si testano in modo affidabile le “skill” di un agente (le istruzioni locali che gli insegnano quando e come usare una capacità) senza colpire API reali, senza costi imprevedibili e senza risultati non deterministici? La risposta che sta emergendo nella comunità DevOps combina due strumenti complementari: Dev Proxy di Microsoft per simulare le API a livello di rete, e Promptfoo per valutare in modo strutturato se una skill funziona meglio di un’altra.Vale la pena approfondire entrambi gli approcci, perché il problema che risolvono — testare comportamento non deterministico in modo ripetibile — è ormai centrale per chiunque gestisca agenti AI in produzione, non solo per chi scrive skill per Claude o Codex.Perché i mock server tradizionali falliscono con gli agenti AIL’approccio classico al test di un’integrazione API è il mock server: si sostituisce l’endpoint reale con uno fittizio, spesso puntando l’applicazione a localhost. Con gli agenti AI questo approccio introduce un problema sottile ma serio: cambiare l’URL di una skill per puntare a un server di test altera il contesto di token visto dal modello. Il modello che si sta testando non è più identico, a livello di token, a quello che verrà effettivamente distribuito in produzione. Questa discrepanza introduce una variabile nascosta che può invalidare i risultati della valutazione e produrre comportamenti inattesi una volta in produzione, quando la skill torna a puntare agli URL reali.Un approccio più efficace consiste nell’usare un proxy leggero che intercetta il traffico HTTP e restituisce dati predefiniti letti da file JSON locali, senza mai modificare gli URL che l’agente chiama. È esattamente il compito per cui è nato Dev Proxy: l’agente continua a chiamare gli URL di produzione, ma riceve risposte deterministiche senza che avvenga alcuna chiamata di rete reale né alcuna gestione di server. I dati si azzerano a ogni esecuzione, il contesto di token resta identico a quello di produzione, e diventa possibile eseguire test di regressione rigorosi all’interno di pipeline CI/CD.Dev Proxy: simulare le API senza toccare il codiceDev Proxy è uno strumento a riga di comando, open source e gratuito, che funziona su qualsiasi piattaforma e con qualsiasi stack tecnologico, perché intercetta le richieste di rete invece di agganciarsi al codice dell’applicazione. Le funzionalità principali coprono scenari che vanno ben oltre il semplice mocking:Simulare errori delle API senza modificare una riga di codice, per verificare che l’app non perda dati dei clienti quando una dipendenza esterna fallisceSimulare rate limiting per verificare che l’applicazione gestisca correttamente il throttlingSimulare latenza e risposte lente per validare le protezioni lato UXGenerare rapidamente mock API CRUD senza scrivere codice destinato a non essere mai distribuitoFornire guida contestuale su permessi e best practice, in particolare per chi integra Microsoft GraphPer il caso specifico degli agenti AI, Dev Proxy include funzionalità dedicate ai language model che permettono di simulare scenari realistici e tracciare l’uso delle risorse, oltre a un tool integrato nel proprio server MCP che fornisce agli agenti di coding raccomandazioni su come costruire le configurazioni. In pratica, un team che sviluppa una skill che chiama un’API esterna può configurare Dev Proxy per intercettare quelle chiamate specifiche e restituire fixture JSON versionate insieme al codice, garantendo che ogni esecuzione della pipeline CI/CD parta da uno stato pulito e riproducibile.Promptfoo: valutare quale versione di una skill funziona meglioSimulare le API risolve solo metà del problema. L’altra metà è capire, in modo misurabile, se una skill fa il proprio lavoro correttamente e se una nuova versione è effettivamente migliore della precedente. È qui che entra in gioco Promptfoo, un framework di valutazione che permette di confrontare due versioni della stessa skill eseguendo gli stessi task fianco a fianco.Il pattern di base è semplice: si mantengono identici il modello, i file di task e i permessi, cambiando solo il file SKILL.md tra una versione e l’altra. Una struttura tipica per confrontare due versioni di una skill review-standards è organizzata così:skill-eval/ ├── promptfooconfig.yaml └── fixtures/ ├── v1/ │ ├── .claude/skills/review-standards/SKILL.md │ └── src/auth.ts └── v2/ ├── .claude/skills/review-standards/SKILL.md └── src/auth.tsNel file di configurazione si definiscono due provider basati sul Claude Agent SDK, identici tranne che per la working_dir, che punta alla fixture v1 o v2:providers: - id: anthropic:claude-agent-sdk label: review-standards-v1 config: model: claude-sonnet-4-6 working_dir: ./fixtures/v1 setting_sources: ['project'] skills: ['review-standards'] append_allowed_tools: ['Read', 'Grep', 'Glob'] - id: anthropic:claude-agent-sdk label: review-standards-v2 config: model: claude-sonnet-4-6 working_dir: ./fixtures/v2 setting_sources: ['project'] skills: ['review-standards'] append_allowed_tools: ['Read', 'Grep', 'Glob']Il parametro setting_sources: ['project'] fa scoprire a Promptfoo i file SKILL.md sotto .claude/skills/, mentre il filtro skills: restringe la sessione a una singola skill e ne abilita automaticamente il tool associato. Per Codex o OpenCode la struttura equivalente usa .agents/skills/ al posto di .claude/skills/, ma la logica di confronto resta identica.Tre livelli di asserzioni per un confronto solidoUna valutazione utile si costruisce a strati. Il primo verifica semplicemente che la skill sia stata invocata:defaultTest: assert: - type: skill-used value: review-standardsClaude espone le chiamate al tool Skill direttamente, e Promptfoo le normalizza nell’asserzione skill-used: questo distingue una risposta corretta ottenuta senza passare dalla skill da una prodotta effettivamente attraverso il workflow che si vuole testare, una distinzione che spesso sfugge a chi valuta solo la qualità della risposta finale.Il secondo livello valuta la qualità del lavoro svolto, per esempio calcolando quanti problemi attesi sono stati effettivamente individuati in una revisione di codice, con una soglia di recall minima. Il terzo livello aggiunge segnali secondari come costo e latenza, utili quando due versioni sono entrambe corrette ma una è molto più lenta o costosa dell’altra:defaultTest: assert: - type: cost threshold: 0.50 - type: latency threshold: 120000Per chi gestisce bundle di skill correlate, un errore comune è testare solo il percorso “felice” di ciascuna skill. Vale la pena aggiungere anche prompt limite che dovrebbero instradare verso una skill vicina, asserendo sia la skill desiderata sia quella che non deve attivarsi, con il costrutto not-skill-used. Questo cattura i casi in cui una skill risolve correttamente il task ma si attiva anche quando non dovrebbe, un problema di “routing” difficile da individuare guardando solo l’output finale.Mettere insieme i due strumenti in CI/CDLa combinazione pratica è: Dev Proxy intercetta le chiamate API reali fatte durante l’esecuzione della skill e restituisce fixture deterministiche, mentre Promptfoo esegue lo stesso set di task contro versioni diverse della skill e assegna un punteggio ai risultati. L’eval si lancia con un semplice comando:npx promptfoo@latest eval -c promptfooconfig.yamlAggiungendo --repeat 3 si ottiene un campione più robusto del comportamento non deterministico dell’agente, mentre --no-cache è utile durante l’iterazione sul testo della skill per garantire risultati sempre freschi. Il comando npx promptfoo@latest view apre una vista web che affianca i risultati delle due versioni, rendendo immediato individuare dove una skill supera l’altra.ConclusioneIl punto centrale di entrambi gli strumenti è lo stesso: eliminare le variabili nascoste che rendono inaffidabile il test di un comportamento non deterministico. Dev Proxy garantisce che il contesto visto dal modello in test sia identico a quello di produzione, eliminando la variabile del cambio di URL. Promptfoo garantisce che il confronto tra due versioni di una skill sia equo, isolando l’unica variabile che conta — il testo della skill stessa — e fornendo asserzioni misurabili su invocazione, qualità, costo e latenza.Per un team che già gestisce pipeline CI/CD tradizionali, l’investimento per aggiungere questo livello di test alle proprie skill AI è relativamente contenuto: entrambi gli strumenti sono open source, si integrano con gli SDK di Claude, Codex e OpenCode, e restituiscono risultati confrontabili senza richiedere infrastruttura dedicata oltre a quella già in uso per il testing tradizionale.Fonti: 4sysops.com, Microsoft Learn – Dev Proxy, Promptfoo – Test Agent Skills
  • 0 Votazioni
    1 Post
    0 Visualizzazioni
    blog@spcnet.itB
    Un server Linux quasi sempre avvisa prima di guastarsi. Il problema è che la maggior parte dei sistemisti guarda i numeri sbagliati: il carico della CPU invece dell’iowait, la percentuale di RAM occupata invece dello swap attivo, lo spazio disco invece degli inode liberi. Il risultato è che i segnali d’allarme restano invisibili finché non si trasformano in un incidente in produzione.Vediamo dieci metriche che vale davvero la pena monitorare su un’infrastruttura Linux, con i comandi per raccoglierle, le soglie di riferimento e — soprattutto — come metterle in relazione tra loro invece di guardarle isolate.1. CPU: l’iowait conta più dell’utilizzo grezzoLa percentuale di utilizzo CPU complessiva è un punto di partenza, ma il segnale utile è nell’%iowait: indica quanto tempo le CPU passano ferme in attesa di I/O su disco invece di eseguire codice applicativo. Un server all’90% di CPU è occupato; un server al 40% di iowait è in sofferenza, anche se il carico “totale” sembra alto allo stesso modo.mpstat -P ALL 1 5Un iowait sostenuto sopra il 20-30% giustifica un’indagine sullo storage con iostat -xz 1 (vedi punto 5).2. Load average rapportato ai core disponibiliIl load average è tra le metriche più fraintese in assoluto: un valore di 8.0 non significa nulla senza sapere quanti core ha la macchina. La regola empirica è che un load sostenuto sopra 1.0 per core indica una possibile saturazione, anche se il collo di bottiglia potrebbe essere CPU, I/O su disco o un altro sottosistema.cat /proc/loadavg nprocLe tre medie (1, 5, 15 minuti) vanno lette come trend: se il valore a 15 minuti cresce costantemente, c’è qualcosa che si sta accumulando — un processo runaway, un thread leak, un collo di bottiglia I/O.3. Memoria: non temere l’uso, temi lo swap attivoLinux usa la RAM libera come page cache, quindi un server che mostra il 95% di memoria occupata non è necessariamente in difficoltà, se gran parte è cache riutilizzabile. Quello che conta davvero è quanta memoria è effettivamente disponibile e se il sistema sta attivamente paginando su swap.free -h grep -E "MemAvailable|SwapTotal|SwapFree" /proc/meminfo vmstat 1 5Un po’ di swap usato non è di per sé un problema: con un vm.swappiness ben tarato, il kernel può spostare pagine “fredde” su swap in modo proattivo senza impatti percepibili. Il segnale d’allarme reale sono le colonne si (swap-in) e so (swap-out) di vmstat: valori sostenuti e diversi da zero, o uno swap che cresce sotto carico, indicano pressione di memoria che degraderà le prestazioni.4. Spazio disco e utilizzo degli inodeFinire lo spazio disco è evidente. Finire gli inode è il killer silenzioso che manda in crisi anche i sistemisti più esperti: si possono avere gigabyte liberi e non riuscire comunque a creare un nuovo file se gli inode sono esauriti.df -h # spazio disco df -i # utilizzo inodeL’esaurimento degli inode capita tipicamente in directory con milioni di file piccoli — code di mail, session store, directory temporanee. Impostate soglie di allerta all’80% sia per lo spazio sia per gli inode, non solo per lo spazio.5. Latenza e throughput I/O del discoIl throughput dice quanti dati si muovono; la latenza dice quanto tempo impiega ogni singola operazione. Un disco che serve scritture sequenziali può avere un throughput ottimo e al contempo una latenza pessima su letture casuali — esattamente il pattern che uccide le prestazioni di un database.iostat -xz 1Le colonne chiave da osservare sono await (tempo medio in ms per servire una richiesta I/O), %util (percentuale di tempo in cui il device è occupato) e r/s/w/s (operazioni al secondo). Un await sopra 20ms per HDD, o sopra 1-2ms per workload sensibili alla latenza su SSD, merita un’indagine. Su HDD e SATA SSD un %util vicino al 100% indica saturazione; sugli NVMe questo indicatore è meno affidabile per via dell’architettura multi-queue, quindi in quel caso conviene fidarsi soprattutto dell’await.6. Traffico di rete e tassi di erroreLa banda utilizzata è la base. Quello che le dashboard spesso non mostrano sono i pacchetti persi, gli errori e le ritrasmissioni, che possono segnalare problemi alla scheda di rete, allo switch o una rete sotto flooding.ip -s link show eth0 ss -s netstat -s | grep -E "retransmit|error|drop"Un contatore di errori sulla NIC che cresce nel tempo indica quasi sempre un problema hardware o di cablaggio. Un tasso di ritrasmissione TCP sopra l’1-2% segnala spesso congestione, perdita di pacchetti o altri problemi di connettività che stanno già impattando le applicazioni.7. File descriptor apertiOgni file, socket e pipe aperti consuma un file descriptor. Applicazioni sotto carico — web server, database, sistemi di messaggistica — possono esaurire il limite per processo o quello di sistema e iniziare a restituire errori “too many open files” che si propagano a cascata.# Uso corrente a livello di sistema cat /proc/sys/fs/file-nr # Massimo di sistema cat /proc/sys/fs/file-max # Per processo ls /proc/<PID>/fd | wc -l cat /proc/<PID>/limits | grep "open files"Se l’utilizzo corrente supera stabilmente il 70-80% del massimo di sistema, è il momento di indagare. Se un processo specifico si avvicina al proprio ulimit, o ha un leak di descriptor (bug da correggere) oppure ha semplicemente bisogno di un limite più alto (tuning). Per capire quale processo trattiene quali file, lsof è lo strumento di riferimento.8. Conteggio di processi e threadPicchi improvvisi nel numero di processi possono indicare fork bomb, cron job impazziti o thread pool applicativi mal configurati. Su applicazioni fortemente multithread, una crescita illimitata del numero di thread è un classico sintomo di bug di concorrenza.ps aux | wc -l cat /proc/sys/kernel/threads-max top -H -p <PID> # thread di un processo specificoConoscere la propria baseline è essenziale: se un web server gira normalmente con 50 worker e improvvisamente se ne vedono 500, qualcosa nella configurazione del servizio o dell’applicazione non va.9. Salute hardware: temperatura e SMARTÈ la metrica che più spesso manca negli stack di monitoraggio software, ed è un errore: le CPU riducono le prestazioni (thermal throttling) prima di spegnersi, quindi si osserva un degrado misterioso delle performance ben prima che compaia un errore esplicito.# Richiede lm-sensors sensors # Stato dischi smartctl -a /dev/sda # IPMI su bare metal ipmitool sdr type TemperatureSu macchine virtuali questi dati possono essere nascosti al guest OS; su server bare metal, temperatura e dati SMART/NVMe rappresentano un livello di preallarme che nessuna metrica software può sostituire. Temperature CPU stabilmente sopra 80°C, o dischi che riportano settori riallocati o errori non correggibili nei dati SMART/NVMe, richiedono intervento immediato.10. Tasso di errore nei log di sistemaLe metriche dicono come sono i numeri; i log dicono perché. Tracciare il tasso di voci ERROR e CRITICAL nel tempo, invece di leggere i log riga per riga, offre un segnale d’allarme precoce prima che il problema diventi un’interruzione di servizio.# systemd journalctl -p err --since "1 hour ago" journalctl -p err --since "1 hour ago" | wc -l # syslog classico grep -iEc "error|critical" /var/log/syslogUn improvviso aumento del tasso di errore nei log, anche se il sistema sembra funzionare normalmente, spesso precede un guasto di minuti o ore. Anche qui, definire una baseline dei tassi di errore “normali” rende evidenti le anomalie.Mettere insieme i pezzi: le baseline battono le soglie fisseSoglie statiche (ad esempio: allerta se la CPU supera l’80%) sono un buon punto di partenza, ma restano strumenti grezzi. La pratica più efficace di monitoraggio Linux è costruire baseline specifiche per il proprio carico di lavoro e allertare sulla deviazione dalla norma, non solo sui valori assoluti.Correlate le metriche, non guardatele a compartimenti stagni: CPU alta combinata con iowait elevato e await del disco in crescita racconta una storia molto più chiara di ciascuna metrica da sola.Allertate sui trend, non sugli scatti isolati: un load average in crescita costante nell’arco di 15 minuti è più utile di un singolo picco.Tenete d’occhio il gap del monitoraggio: il tempo che passa tra il superamento di una soglia e l’intervento umano è dove gli incidenti crescono. Automatizzate tutto ciò che potete, ad esempio con Prometheus + node_exporter + Alertmanager per la raccolta e la notifica, o con Grafana per la visualizzazione delle baseline nel tempo.Su una manciata di server, eseguire questi controlli manualmente da riga di comando funziona bene. Quando l’infrastruttura cresce a decine o centinaia di macchine, diventa poco pratico farlo a mano: è il momento di investire in una piattaforma di observability centralizzata che aggreghi queste metriche, applichi soglie dinamiche e correli gli eventi tra sistemi diversi.Gli strumenti cambiano nel tempo — oggi iostat e vmstat, domani forse eBPF-based tooling come bpftrace — ma i fondamentali restano gli stessi: sapere cosa guardare, in che relazione, e con quale baseline confrontarlo.Fonte: LinuxBlog.io
  • 0 Votazioni
    1 Post
    0 Visualizzazioni
    blog@spcnet.itB
    Cosa cambia con la GA dei browser toolsDal 1° luglio 2026 i browser tools per GitHub Copilot in Visual Studio Code sono generalmente disponibili (GA) e attivi di default. Non si tratta di una semplice estensione per il debugging: gli agenti di Copilot ottengono ora le stesse azioni che un developer compirebbe normalmente in un browser reale — aprire pagine, navigare, cliccare, digitare, gestire dialog, leggere il contenuto del DOM, catturare errori di console e screenshot, fino all’esecuzione di flussi scriptati quando conviene eseguire una sequenza di passi invece di tante singole chiamate a tool.Per chi lavora quotidianamente su applicazioni web — sviluppo frontend, test end-to-end, troubleshooting di regressioni UI — questa funzionalità cambia sensibilmente il flusso di lavoro con l’AI: l’agente può verificare da solo se una modifica ha funzionato, invece di chiedere all’utente di incollare uno screenshot o l’output della console.Cosa può fare davvero l’agente nel browserSotto il cofano, VS Code espone all’agente un set di azioni equivalenti a quelle di uno strumento di automazione come Playwright, ma integrate direttamente nell’editor:Apertura e navigazione di pagine, click, digitazione testo, hover, drag and drop, gestione di dialog nativi del browser.Lettura del contenuto della pagina, cattura degli errori di console e degli screenshot per il debugging visivo.Esecuzione di flussi scriptati quando una sequenza di passi predefinita è più efficiente di singole chiamate a tool separate.Le DevTools restano comunque disponibili direttamente nella toolbar del browser integrato, così lo sviluppatore può ispezionare elementi, leggere la console e fare debug manuale in parallelo a quanto fa l’agente.Il modello di permessi: cosa resta sotto il tuo controlloDare a un agente AI la capacità di pilotare un browser reale solleva ovvie domande di sicurezza. Il team di VS Code ha progettato il modello di permessi attorno a tre principi:Le tue schede restano private di defaultL’agente non può leggere né interagire con una scheda che hai aperto tu finché non selezioni esplicitamente Share with Agent. L’accesso concesso può essere revocato in qualsiasi momento.Le schede dell’agente sono isolateLe pagine che l’agente apre autonomamente girano in sessioni pulite, senza accesso a cookie o storage della tua normale sessione di navigazione. Se esegui più agenti in parallelo nella finestra Agents, ciascuno mantiene le proprie schede private rispetto agli altri.I permessi sensibili restano manualiFotocamera, microfono, geolocalizzazione, notifiche e lettura della clipboard non vengono mai concessi automaticamente: ogni sito richiede un’approvazione esplicita da parte tua, e l’agente non può approvarli al posto tuo. Solo azioni a basso rischio, come la scrittura sanificata sulla clipboard, sono consentite di default.Controlli enterprise e configurazione della retePer chi gestisce flotte di postazioni sviluppatore, VS Code espone controlli centralizzati pensati proprio per governare questa superficie:// settings.json — disabilitare completamente i browser tools
{
 "workbench.browser.enableChatTools": false
}

// Limitare i domini raggiungibili dagli agenti e dal browser integrato
{
 "chat.agent.networkFilter": true,
 "chat.agent.allowedNetworkDomains": [
 "*.miaazienda.it",
 "github.com"
 ],
 "chat.agent.deniedNetworkDomains": [
 "*.pagamenti-esterni.com"
 ]
}La regola pratica da tenere a mente in produzione: gli elenchi di domini negati hanno sempre precedenza su quelli consentiti, ed entrambi supportano wildcard (ad esempio *.example.com). Restano inoltre attivi i normali prompt di Workspace Trust e le approvazioni già previste per gli altri tool dell’agente, quindi l’attivazione dei browser tools non aggira le policy di sicurezza esistenti a livello di workspace.Un caso d’uso pratico: test end-to-end guidato dall’agenteUn flusso tipico che questa funzionalità sblocca è la verifica autonoma di una modifica UI. Dopo aver chiesto a Copilot di correggere un bug nel form di login, si può semplicemente chiedere all’agente di “aprire l’app in locale, compilare il form con credenziali di test e verificare che il redirect alla dashboard funzioni”. L’agente aprirà una scheda browser isolata, eseguirà i passaggi, catturerà eventuali errori di console e screenshot, e riporterà l’esito direttamente in chat, senza che lo sviluppatore debba fare context switch verso il browser.Per team con suite di test end-to-end già basate su Playwright o Cypress, i browser tools non sostituiscono la pipeline CI, ma accorciano il ciclo di iterazione locale: si individua un problema, si corregge, si verifica visivamente, il tutto restando nell’editor.Come iniziareLa funzionalità è disponibile sia nella finestra dell’editor sia nella finestra Agents. È sufficiente aggiornare VS Code all’ultima versione e chiedere all’agente di aprire o testare una pagina: i browser tools sono attivi per impostazione predefinita da GA in poi. Per la documentazione completa, si vedano le pagine ufficiali sui browser tools per gli agenti e la relativa guida al testing con agenti nel browser.ConclusioneIl passaggio a GA dei browser tools segna un salto di maturità per gli agenti AI integrati in VS Code: da assistenti che scrivono codice sulla fiducia, a strumenti capaci di verificare autonomamente il proprio lavoro in un ambiente reale. Per i team enterprise, la combinazione di isolamento delle sessioni, permessi granulari e filtri di rete configurabili rende la funzionalità adottabile anche in contesti con requisiti di sicurezza stringenti, a patto di configurare fin da subito le allowlist di dominio e di rivedere periodicamente chi ha accesso a quali capacità.Fonte: GitHub Changelog — Browser tools for GitHub Copilot in VS Code are generally available
  • 0 Votazioni
    1 Post
    0 Visualizzazioni
    blog@spcnet.itB
    PostgreSQL 19 Beta 1: due novità che meritano attenzioneIl 4 giugno 2026 il PostgreSQL Global Development Group ha rilasciato la prima beta di PostgreSQL 19, con disponibilità generale attesa tra settembre e ottobre 2026. Tra le decine di miglioramenti elencati nelle release notes, due si distinguono per l’impatto pratico su chi gestisce database in produzione: il supporto nativo alle SQL Property Graph Queries (SQL/PGQ) e il nuovo comando REPACK, che introduce finalmente una modalità CONCURRENTLY per riorganizzare le tabelle senza bloccare le scritture. Vale la pena approfondire entrambe, perché rispondono a due esigenze molto concrete: interrogare relazioni complesse senza migrare verso un database a grafo dedicato, e liberare spazio su disco senza fermare l’applicazione.SQL/PGQ: query a grafo sulle tue tabelle relazionali esistentiSQL/PGQ è la Parte 16 dello standard ISO/IEC 9075 (SQL:2023) e definisce un modo standard per esprimere query di pattern matching su grafi usando sintassi SQL. La scelta implementativa di PostgreSQL è particolarmente interessante: un property graph non è una nuova struttura di storage, ma una vista in sola lettura sopra tabelle relazionali già esistenti. I dati restano dove sono sempre stati — in tabelle normali, con vincoli di chiave primaria ed esterna — e vengono semplicemente “esposti” come grafo per le query che lo richiedono. Query relazionali e query a grafo condividono lo stesso planner e lo stesso motore di esecuzione, e possono anche essere combinate nella stessa istruzione.Per capire la sintassi conviene partire da uno schema minimo di e-commerce:CREATE TABLE products ( product_no integer PRIMARY KEY, name varchar, price numeric ); CREATE TABLE customers ( customer_id integer PRIMARY KEY, name varchar, address varchar ); CREATE TABLE orders ( order_id integer PRIMARY KEY, ordered_when date ); CREATE TABLE order_items ( order_items_id integer PRIMARY KEY, order_id integer REFERENCES orders (order_id), product_no integer REFERENCES products (product_no), quantity integer ); CREATE TABLE customer_orders ( customer_orders_id integer PRIMARY KEY, customer_id integer REFERENCES customers (customer_id), order_id integer REFERENCES orders (order_id) );Le prime tre tabelle diventano i vertici del grafo, le ultime due — grazie alle chiavi esterne che collegano coppie di vertici — diventano gli archi. La definizione del grafo è dichiarativa:CREATE PROPERTY GRAPH myshop VERTEX TABLES ( products LABEL product, customers LABEL customer, orders LABEL "order" ) EDGE TABLES ( order_items SOURCE orders DESTINATION products LABEL contains, customer_orders SOURCE customers DESTINATION orders LABEL has_placed );Da qui in poi si può interrogare il grafo con la clausola GRAPH_TABLE e la sintassi di pattern matching, invece delle classiche JOIN:SELECT customer_name FROM GRAPH_TABLE ( myshop MATCH (c IS customer)-[IS has_placed]->(o IS "order" WHERE o.ordered_when = current_date) COLUMNS (c.name AS customer_name) );che corrisponde, dal punto di vista relazionale, a:SELECT customers.name FROM customers JOIN customer_orders USING (customer_id) JOIN orders USING (order_id) WHERE orders.ordered_when = current_date;La differenza diventa evidente man mano che i pattern si complicano: catene di relazioni a più salti, percorsi variabili, ricerche “chi è collegato a chi entro N passaggi” sono espressioni naturali in sintassi a grafo, ma diventano rapidamente catene di self-join illeggibili in SQL relazionale puro. Per chi lavora su organigrammi, grafi di dipendenze tra servizi, reti di frodi o raccomandazioni, SQL/PGQ evita di dover affiancare un database a grafo dedicato (Neo4j, Amazon Neptune) solo per questo tipo di interrogazioni, con tutto il costo operativo che una piattaforma aggiuntiva comporta.È bene ricordare che, essendo una vista sopra le tabelle esistenti, un grafo così definito eredita automaticamente permessi, vincoli e integrità referenziale già presenti: non introduce una nuova copia dei dati da tenere sincronizzata.REPACK CONCURRENTLY: addio alle finestre di manutenzione per VACUUM FULLChi amministra PostgreSQL conosce bene il dilemma tra VACUUM normale, che non recupera sempre tutto lo spazio occupato da tuple morte, e VACUUM FULL (o CLUSTER), che lo recupera per intero ma richiede un ACCESS EXCLUSIVE lock per l’intera durata dell’operazione — inaccettabile su una tabella calda in produzione. PostgreSQL 19 risolve il problema unificando le due funzionalità in un unico comando, REPACK, e aggiungendo un’opzione CONCURRENTLY che cambia le regole del gioco.-- Riorganizza una tabella riscrivendola su nuovo file, senza clustering REPACK employees; -- Riorganizza mantenendo l'app pienamente operativa in lettura/scrittura REPACK (CONCURRENTLY) employees; -- Repack con clustering fisico secondo un indice, più ANALYZE finale REPACK (ANALYZE, VERBOSE) cases (district, case_nr);Il meccanismo interno spiega perché questa opzione è sicura da usare su tabelle attive: REPACK copia il contenuto della tabella (ignorando le tuple morte) in un nuovo file, ordinato secondo l’indice specificato se presente, e crea nuovi file anche per gli indici collegati. Con CONCURRENTLY, l’ACCESS EXCLUSIVE lock viene acquisito solo per lo scambio finale dei file: le modifiche avvenute durante la copia vengono catturate tramite logical decoding e riapplicate prima dello swap, che quindi risulta tipicamente molto breve. La tabella resta leggibile e scrivibile per la quasi totalità dell’operazione.Ci sono comunque limiti operativi da conoscere prima di affidarsi a questa modalità in produzione: CONCURRENTLY non è disponibile su tabelle UNLOGGED, su tabelle partizionate, su tabelle prive di chiave primaria e di un’identità di replica basata su indice, su cataloghi di sistema o tabelle TOAST, né dentro un blocco di transazione. Serve inoltre che max_repack_replication_slots consenta la creazione di uno slot di replica aggiuntivo, dato che il meccanismo si appoggia alla logical decoding. Va anche segnalato che REPACK CONCURRENTLY non è MVCC-safe nello stesso senso di altre operazioni online, quindi vale la pena leggere con attenzione la sezione sulle caveat di MVCC nella documentazione prima di pianificarne l’adozione su carichi critici.Il progresso dell’operazione è osservabile in tempo reale tramite la vista pg_stat_progress_repack, utile per stimare i tempi su tabelle di grandi dimensioni prima di schedulare l’operazione su ambienti con SLA stringenti.Altre novità rilevanti per chi amministra database in produzioneOltre alle due funzionalità principali, la beta introduce una serie di miglioramenti che meritano di essere tenuti d’occhio in fase di test: l’autovacuum può ora usare worker paralleli (autovacuum_max_parallel_workers), le inserzioni con controlli di chiave esterna sono fino a due volte più veloci, e il nuovo comando WAIT FOR LSN permette di implementare pattern “read-your-writes” verso le repliche senza più bisogno di sleep applicativi o di forzare le letture sul primario. Da segnalare anche un cambiamento di default che avrà impatto diretto sui workload analitici: la compilazione JIT (jit) è ora disattivata di default, il che può alterare sensibilmente i piani e i tempi di query che finora beneficiavano (o soffrivano) silenziosamente della compilazione just-in-time.ConclusionePostgreSQL 19 conferma la strategia degli ultimi anni: estendere le capacità del database relazionale invece di costringere i team a moltiplicare le piattaforme specializzate. SQL/PGQ evita un database a grafo dedicato per molti casi d’uso comuni, mentre REPACK CONCURRENTLY chiude una lacuna operativa che gli amministratori PostgreSQL si portavano dietro da anni. Trattandosi ancora di una beta, entrambe le funzionalità vanno testate su ambienti non di produzione prima della GA prevista per l’autunno 2026, ma la direzione presa merita già di essere seguita da vicino da chi pianifica le prossime migrazioni.Fonte: PostgreSQL Global Development Group — PostgreSQL 19 Beta 1 Released!