[{"data":1,"prerenderedAt":2280},["ShallowReactive",2],{"docs-pages-en":3,"doc-en-changelog-sdk-ruby":308},[4,9,15,20,25,30,35,41,52,60,69,77,84,92,96,105,109,117,122,127,132,138,143,148,153,158,163,169,174,179,184,189,194,199,204,209,214,219,224,229,234,239,244,249,254,260,265,269,273,278,283,288,293,298,303],{"path":5,"title":6,"description":7,"order":8,"group":8,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fpermissions","Who can do what","[object Object]",null,{"path":10,"title":11,"description":12,"order":13,"group":14,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Finstallation","Installation","Install CloseYourIt on your own server with one command.",1,"start",{"path":16,"title":17,"description":18,"order":19,"group":14,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fsettings","Settings","Every setting in the .env file, what it does and which ones you must never change.",2,{"path":21,"title":22,"description":23,"order":24,"group":14,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fdatabase","Database","What the database is, what is inside, how long data stays and how much room it takes.",3,{"path":26,"title":27,"description":28,"order":29,"group":14,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fupdates-and-backups","Updates and backups","Update to a new version, back up and restore the database, check the install.",4,{"path":31,"title":32,"description":33,"order":34,"group":14,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Ftroubleshooting","Troubleshooting","What to check when the install, the certificate, email or incoming data do not work.",5,{"path":36,"title":37,"description":38,"order":39,"group":40,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fconnect-your-apps","Connect your apps","Every tool that sends data to CloseYourIt, and what each one collects.",6,"connect",{"path":42,"title":43,"description":44,"order":45,"group":8,"parent":46,"package":47,"note":48,"collects":49,"status":8},"\u002Fdocs\u002Fsdk-ruby","Ruby \u002F Rails","The closeyourit-ruby gem sends errors, logs, slow queries and job metrics from a Rails app.",7,"connect-your-apps","closeyourit-ruby","Errors, logs, slow queries and methods, background jobs.",{"errors":50,"logs":50,"performance":50,"visits":51,"servers":51},"full","none",{"path":53,"title":54,"description":55,"order":56,"group":8,"parent":46,"package":57,"note":58,"collects":59,"status":8},"\u002Fdocs\u002Fsdk-javascript","JavaScript","The @bussolabs\u002Fcloseyourit-js package works in the browser and on Node 20.16 or newer.",8,"@bussolabs\u002Fcloseyourit-js","Browser and Node, framework adapters and database queries from 0.13.0.",{"errors":50,"logs":50,"performance":50,"visits":50,"servers":51},{"path":61,"title":62,"description":63,"order":64,"group":8,"parent":46,"package":65,"note":66,"collects":67,"status":8},"\u002Fdocs\u002Fsdk-dart","Dart \u002F Flutter","The closeyourit package captures the errors of Flutter apps, even when the phone is offline.",9,"closeyourit","Public errors, logs and metrics from 0.9.3.",{"errors":50,"logs":68,"performance":68,"visits":51,"servers":51},"partial",{"path":70,"title":71,"description":72,"order":73,"group":8,"parent":46,"package":65,"note":74,"collects":75,"status":76},"\u002Fdocs\u002Fsdk-python","Python","The closeyourit package sends errors, logs and metrics from server-side Python applications.",10,"Server side. SQLAlchemy; Django query monitoring and FastAPI\u002FStarlette from 0.4.0.",{"errors":50,"logs":50,"performance":68,"visits":51,"servers":51},"pre_alpha",{"path":78,"title":79,"description":80,"order":81,"group":8,"parent":46,"package":79,"note":82,"collects":83,"status":8},"\u002Fdocs\u002Fsdk-sentry","Sentry SDK","Send errors with a compatible Sentry SDK; sessions and crashes have separate profiles.",11,"Compatible errors; sessions and crashes require a verified profile.",{"errors":50,"logs":51,"performance":51,"visits":51,"servers":51},{"path":85,"title":86,"description":87,"order":88,"group":8,"parent":46,"package":89,"note":90,"collects":91,"status":8},"\u002Fdocs\u002Fagent-server","Server agent","A small program on the server that sends the state of the machine every 60 seconds.",12,"closeyourit-agent","CPU, memory, disks, network, containers and services.",{"errors":51,"logs":68,"performance":51,"visits":51,"servers":50},{"path":93,"title":94,"description":95,"order":88,"group":40,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fnuxt","Vue and Nuxt","Connect Nuxt browser errors and Nitro server errors without exposing a server token.",{"path":97,"title":98,"description":99,"order":100,"group":8,"parent":46,"package":101,"note":102,"collects":103,"status":104},"\u002Fdocs\u002Fagent-kubernetes","Kubernetes","A read-only observer of the cluster: one copy per cluster.",13,"closeyourit-kube","Machines, apps and error events of the cluster.",{"errors":51,"logs":51,"performance":51,"visits":51,"servers":50},"coming",{"path":106,"title":107,"description":108,"order":100,"group":40,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fopentelemetry","OpenTelemetry","Send server traces, metrics and logs through the optional OTLP receiver.",{"path":110,"title":111,"description":112,"order":113,"group":8,"parent":46,"package":114,"note":115,"collects":116,"status":8},"\u002Fdocs\u002Fcli","cyi CLI","The closeyourit command, cyi for short: manage projects, errors and tickets from the terminal.",14,"@bussolabs\u002Fcloseyourit-cli","It collects no data: it drives CloseYourIt from the terminal.",{"errors":51,"logs":51,"performance":51,"visits":51,"servers":51},{"path":118,"title":119,"description":120,"order":121,"group":40,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fhttp-api","HTTP API","Send errors, logs, metrics and page views with plain HTTP requests, without an SDK.",15,{"path":123,"title":124,"description":125,"order":126,"group":40,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fgithub-app","GitHub","Connect GitHub repositories to tickets and releases with your own GitHub App.",16,{"path":128,"title":129,"description":130,"order":131,"group":40,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fingest-gateway","Ingest gateway","Keep incoming errors, logs and metrics safe when the app is slow or restarting.",17,{"path":133,"title":134,"description":135,"order":136,"group":137,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fai","AI","Turn on assistant, analysis, dictation and smart search with a CloseYourIt AI key or your own provider.",18,"automation",{"path":139,"title":140,"description":141,"order":142,"group":137,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fautomator","Automator","Let tickets be worked automatically on your own Linux machine, with Claude Code, Codex or both.",19,{"path":144,"title":145,"description":146,"order":147,"group":40,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fstack-coverage","Frameworks and stack coverage","Choose a published SDK or understand the limits of a locally tested integration.",20,{"path":149,"title":150,"description":151,"order":152,"group":40,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fmonitoring","Traces, measurements and sessions","Explore the new signals, compare releases and recover original error locations.",21,{"path":154,"title":155,"description":156,"order":157,"group":40,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fnode-database","Node databases","Monitor slow and repeated queries with pg, mysql2, Drizzle and Prisma PostgreSQL.",22,{"path":159,"title":160,"description":161,"order":162,"group":137,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fclaude-code","Claude Code","CloseYourIt inside Claude Code, in a column next to the conversation with production and your open tickets.",23,{"path":164,"title":165,"description":166,"order":167,"group":168,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Ftickets","Tickets and ideas","Open and follow tickets on the board, group them into milestones, ask questions and turn voted ideas into work.",30,"use",{"path":170,"title":171,"description":172,"order":173,"group":168,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Ferrors","Errors","How your apps' errors become single rows, and how to resolve, ignore, merge or turn them into tickets.",31,{"path":175,"title":176,"description":177,"order":178,"group":168,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fperformance","Performance","Find slow queries and methods, read the problems detected automatically and get an alert when one appears.",32,{"path":180,"title":181,"description":182,"order":183,"group":168,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Flogs","Logs","Search your apps' messages, follow a request from start to end and link a message to an error or a ticket.",33,{"path":185,"title":186,"description":187,"order":188,"group":168,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fsecrets","Secrets","Passwords, keys and private files in one place, per project and environment, read by your app without a .env on disk.",34,{"path":190,"title":191,"description":192,"order":193,"group":168,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fservers","Servers","The state of your machines on one page, with history and alerts when something breaks or fills up.",35,{"path":195,"title":196,"description":197,"order":198,"group":168,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fuptime","Uptime","Check that your sites answer, keep count of outages and show them to customers on a status page.",36,{"path":200,"title":201,"description":202,"order":203,"group":168,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fcrons","Scheduled jobs","Notice when a job that should run on its own stops running, or runs and ends badly.",37,{"path":205,"title":206,"description":207,"order":208,"group":168,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Falerts","Alerts","The rules that create an alert, the notification center and where each person chooses to receive them.",38,{"path":210,"title":211,"description":212,"order":213,"group":168,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fhelpdesk","Help desk","Visitors of a project's site write to the team with the \"Need help?\" button, and the request lands in the right project.",39,{"path":215,"title":216,"description":217,"order":218,"group":168,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fanalytics","Site analytics","How many people visit the site, what they look at and where they come from, without cookies.",40,{"path":220,"title":221,"description":222,"order":223,"group":168,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Freplays","Session replay","Record how people move through the site and watch it back like a video, even next to an error.",41,{"path":225,"title":226,"description":227,"order":228,"group":168,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Freleases","Releases","The versions running in each environment, bound to GitHub tags, and the errors that come back after a fix.",42,{"path":230,"title":231,"description":232,"order":233,"group":168,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fvulnerabilities","Vulnerabilities","Known security problems in your projects' libraries, and the languages that no longer get fixes.",43,{"path":235,"title":236,"description":237,"order":238,"group":168,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fseo","SEO","CloseYourIt visits your sites like a search engine and tells you what keeps your pages from being found.",44,{"path":240,"title":241,"description":242,"order":243,"group":168,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fknowledge","Knowledge base","Write notes, decisions and guides for your projects, find them by meaning and ask questions with sources.",45,{"path":245,"title":246,"description":247,"order":248,"group":168,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fagents","AI agents","Which tickets agents take, what they hand you, where you decide and how each machine is measured.",46,{"path":250,"title":251,"description":252,"order":253,"group":14,"parent":8,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fchangelog","Versions","Every CloseYourIt system with its latest version, and the notes of each release.",50,{"path":255,"title":256,"description":257,"order":258,"group":8,"parent":259,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fchangelog-app","App","Every stable version of App, newest first.",51,"changelog",{"path":261,"title":262,"description":263,"order":264,"group":8,"parent":259,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fchangelog-cli","Command line (cyi)","Every stable version of Command line (cyi), newest first.",52,{"path":266,"title":140,"description":267,"order":268,"group":8,"parent":259,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fchangelog-automator","Every stable version of Automator, newest first.",53,{"path":270,"title":86,"description":271,"order":272,"group":8,"parent":259,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fchangelog-agent-server","Every stable version of Server agent, newest first.",54,{"path":274,"title":275,"description":276,"order":277,"group":8,"parent":259,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fchangelog-agent-kubernetes","Kubernetes agent","Every stable version of Kubernetes agent, newest first.",55,{"path":279,"title":280,"description":281,"order":282,"group":8,"parent":259,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fchangelog-sdk-javascript","JavaScript SDK","Every stable version of JavaScript SDK, newest first.",56,{"path":284,"title":285,"description":286,"order":287,"group":8,"parent":259,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fchangelog-sdk-ruby","Ruby SDK","Every stable version of Ruby SDK, newest first.",57,{"path":289,"title":290,"description":291,"order":292,"group":8,"parent":259,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fchangelog-sdk-python","Python SDK","Every stable version of Python SDK, newest first.",58,{"path":294,"title":295,"description":296,"order":297,"group":8,"parent":259,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fchangelog-sdk-dart","Dart SDK","Every stable version of Dart SDK, newest first.",59,{"path":299,"title":300,"description":301,"order":302,"group":8,"parent":259,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fchangelog-skills","Skills for AI assistants","Every stable version of Skills for AI assistants, newest first.",60,{"path":304,"title":305,"description":306,"order":307,"group":8,"parent":259,"package":8,"note":8,"collects":8,"status":8},"\u002Fdocs\u002Fchangelog-site","Website and docs","Every stable version of Website and docs, newest first.",61,{"id":309,"title":285,"body":310,"collects":8,"description":286,"extension":2274,"group":8,"meta":2275,"navigation":2276,"note":8,"order":287,"package":8,"parent":259,"path":284,"seo":2277,"status":8,"stem":2278,"__hash__":2279},"docs_en\u002Fdocs\u002Fchangelog-sdk-ruby.md",{"type":311,"value":312,"toc":2248},"minimark",[313,317,322,328,338,342,346,386,390,395,413,417,425,429,433,441,445,450,458,462,470,474,478,490,494,520,524,528,550,554,558,576,580,584,595,599,603,611,615,619,661,666,738,742,746,798,802,876,880,884,1126,1130,1324,1329,1437,1441,1445,1504,1508,1512,1548,1552,1714,1718,1722,1753,1757,1761,1821,1825,1829,1884,1888,1927,1931,1935,1986,1990,1994,2118,2122,2136,2140,2144,2152,2156,2160,2220,2224,2239,2243],[314,315,316],"p",{},"Release notes are written in Italian.",[318,319,321],"h2",{"id":320},"_0121-2026-10-07","0.12.1 · 2026-10-07",[314,323,324],{},[325,326,327],"strong",{},"Corretto",[329,330,331],"ul",{},[332,333,334,337],"li",{},[325,335,336],{},"La 0.12.0 non è arrivata su RubyGems."," Questa versione contiene le stesse modifiche.",[318,339,341],{"id":340},"_0120-2026-10-07","0.12.0 · 2026-10-07",[314,343,344],{},[325,345,327],{},[329,347,348,362,372],{},[332,349,350,358,359,361],{},[325,351,352,353,357],{},"Il body della richiesta resta a casa senza ",[354,355,356],"code",{},"send_pii","."," Con la privacy spenta i parametri dei form non vengono più allegati agli errori, come promesso dalla documentazione. Chi li vuole attiva ",[354,360,356],{},". (CYRB-28)",[332,363,364,367,368,371],{},[325,365,366],{},"I filtri di Rails valgono anche per la gemma."," Le chiavi dichiarate in ",[354,369,370],{},"config.filter_parameters"," dell'app vengono redatte in errori, tag e metriche senza ripeterle nella configurazione. (CYRB-28)",[332,373,374,377,378,381,382,385],{},[325,375,376],{},"Argomenti dei metodi lenti redatti."," Con ",[354,379,380],{},"capture_method_arguments"," anche gli argomenti posizionali passano dallo scrubber dei messaggi (credenziali e ",[354,383,384],{},"scrub_message_patterns","). (CYRB-28)",[318,387,389],{"id":388},"_0110-2026-10-04","0.11.0 · 2026-10-04",[314,391,392],{},[325,393,394],{},"Aggiunto",[329,396,397,403],{},[332,398,399,402],{},[325,400,401],{},"Contesto dei tentativi di lavoro."," ActiveJob e Sidekiq inviano il contesto job v1 con durata, attesa e ritardo programmato separati. Tempi o esiti non osservabili restano sconosciuti. (CYRA-972)",[332,404,405,408,409,412],{},[325,406,407],{},"Log del ciclo di vita dei job."," L'opzione ",[354,410,411],{},"job_lifecycle_logs",", spenta per default, registra gli esiti osservati senza argomenti o risultati e senza duplicare ActiveJob dentro Sidekiq. (CYRA-972)",[314,414,415],{},[325,416,327],{},[329,418,419],{},[332,420,421,424],{},[325,422,423],{},"SQL protetto anche con stringhe dollar-quoted."," I valori PostgreSQL racchiusi fra delimitatori dollar-quoted vengono redatti prima dell'invio della telemetria.",[318,426,428],{"id":427},"_0102-2026-10-01","0.10.2 · 2026-10-01",[314,430,431],{},[325,432,327],{},[329,434,435],{},[332,436,437,440],{},[325,438,439],{},"Pubblicazione riparata."," La 0.10.1 non è arrivata su RubyGems: questa versione contiene le stesse modifiche.",[318,442,444],{"id":443},"_0101-2026-10-01","0.10.1 · 2026-10-01",[314,446,447],{},[325,448,449],{},"Modificato",[329,451,452],{},[332,453,454,457],{},[325,455,456],{},"Le query dell'app costano meno."," Il punto del codice da cui parte una query si calcola solo per quelle lente o da analizzare, non più per ogni query. (CYRB-26)",[314,459,460],{},[325,461,327],{},[329,463,464],{},[332,465,466,469],{},[325,467,468],{},"L'attesa in coda dei lavori non conta più i rinvii voluti."," Un lavoro rimandato apposta, o ritentato dopo un errore, risultava in ritardo anche se partiva puntuale. Ora l'attesa si misura dall'ora prevista di partenza. (CYRB-27)",[318,471,473],{"id":472},"_0100-2026-09-14","0.10.0 · 2026-09-14",[314,475,476],{},[325,477,394],{},[329,479,480],{},[332,481,482,485,486,489],{},[325,483,484],{},"Si sceglie quanto attendere alla chiusura."," Nuova opzione ",[354,487,488],{},"shutdown_timeout",": dice quanto tempo dare all'invio degli eventi rimasti prima di chiudere. (CYRB-24)",[314,491,492],{},[325,493,327],{},[329,495,496,502,508,514],{},[332,497,498,501],{},[325,499,500],{},"Alla chiusura del programma gli eventi in coda non si perdono più in silenzio."," L'attesa era troppo corta e l'ultimo gruppo spariva, dato per consegnato. Ora l'attesa basta a completare l'invio e ciò che resta indietro viene contato. (CYRB-24)",[332,503,504,507],{},[325,505,506],{},"Un messaggio malformato non porta più via gli altri."," In un gruppo di voci di registro viene scartata solo quella che dà problemi: le altre partono. (CYRB-24)",[332,509,510,513],{},[325,511,512],{},"La misurazione dei tempi non fa più fallire il metodo dell'applicazione."," Un guasto interno alla misurazione tornava a chi aveva chiamato il metodo. Ora viene registrato e assorbito. (CYRB-24)",[332,515,516,519],{},[325,517,518],{},"I controlli automatici tornano a girare su ogni proposta di modifica."," Le verifiche erano ferme e le modifiche passavano senza prova. Ora ogni proposta viene controllata prima di essere unita. (CITM-8)",[318,521,523],{"id":522},"_094-2026-09-07","0.9.4 · 2026-09-07",[314,525,526],{},[325,527,327],{},[329,529,530,540],{},[332,531,532,535,536,539],{},[325,533,534],{},"La credenziale nel testo di un messaggio non parte più in chiaro"," (CYRB-23). Un\n",[354,537,538],{},"Authorization: Bearer …"," finito in un errore o in un log ora è redatto di serie, senza\nconfigurazione: restano leggibili chiave e schema, sparisce il valore.",[332,541,542,545,546,549],{},[325,543,544],{},"Il token non segue più un redirect su un'altra porta"," (CYRB-22). Un redirect che teneva lo stesso\nnome host ma cambiava porta riceveva ancora il ",[354,547,548],{},"Bearer",": sullo stesso server è un servizio diverso.\nOra l'invio richiede stesso host, stessa porta e schema non degradato.",[318,551,553],{"id":552},"_093-2026-09-03","0.9.3 · 2026-09-03",[314,555,556],{},[325,557,449],{},[329,559,560],{},[332,561,562,565,566,575],{},[325,563,564],{},"Il README dice dove finisce la gemma e dove iniziano gli altri SDK"," (CYRB-21). Non lascia più\nintendere di fare le stesse cose di JavaScript, Dart e Python: dice cosa esiste solo qui e rimanda\nalla tabella unica di cosa c'è dove\n(",[567,568,572],"a",{"href":569,"rel":570},"https:\u002F\u002Fgithub.com\u002Fbussolabs\u002Fcloseyourit-docs\u002Fblob\u002Fmain\u002Fcompatibility\u002Fsdk-feature-parity.md",[571],"nofollow",[354,573,574],{},"sdk-feature-parity.md",").",[318,577,579],{"id":578},"_092-2026-08-31","0.9.2 · 2026-08-31",[314,581,582],{},[325,583,327],{},[329,585,586],{},[332,587,588,594],{},[325,589,590,593],{},[354,591,592],{},"CloseYourIt.used"," è davvero chiamabile."," Il punto d'ingresso della telemetria d'uso era\nfinito per sbaglio fra i metodi interni; e due rami senza prova tenevano il rilascio sotto la\nsoglia di copertura. La 0.9.1 esiste come etichetta ma non è mai stata pubblicata.",[318,596,598],{"id":597},"_091-2026-08-31","0.9.1 · 2026-08-31",[314,600,601],{},[325,602,327],{},[329,604,605],{},[332,606,607,610],{},[325,608,609],{},"Il rilascio non si ferma più su se stesso."," Il controllo che confronta l'etichetta del rilascio\ncol numero dentro la libreria aveva quel numero scritto a mano nei propri test: ogni aggiornamento\nli faceva diventare rossi. Ora lo leggono dalla libreria. La 0.9.0 esiste come etichetta ma non è\nmai stata pubblicata: si è fermata qui.",[318,612,614],{"id":613},"_090-2026-08-31","0.9.0 · 2026-08-31",[314,616,617],{},[325,618,394],{},[329,620,621],{},[332,622,623,626,627,630,631,634,635,638,639,642,643,646,647,650,651,654,655,658,659,357],{},[325,624,625],{},"Telemetria d'uso (CYSK-29)",": la gemma dichiara quali rotte (",[354,628,629],{},"Controller#action",", mai l'URL),\njob e chiavi custom (",[354,632,633],{},"CloseYourIt.used(\"chiave\")",") vengono davvero eseguiti — un flush ogni 5\nminuti per processo verso ",[354,636,637],{},"\u002Fapi\u002Fv1\u002Fprojects\u002F:id\u002Fusages",". I conteggi sono indicativi, solo\n",[354,640,641],{},"last_seen_at"," è portante; oltre ",[354,644,645],{},"usage_max_symbols"," (2000) il flush dichiara ",[354,648,649],{},"truncated",", che\nlato scanner squalifica il kind. Nessun dato utente nel payload per costruzione. Interruttori:\n",[354,652,653],{},"usage_enabled"," (default ON), ",[354,656,657],{},"usage_flush_interval",", ",[354,660,645],{},[314,662,663],{},[325,664,665],{},"Sicurezza",[329,667,668,689],{},[332,669,670,673,674,677,678,681,682,685,686,688],{},[325,671,672],{},"Non si pubblica più una versione col nome di un'altra",": prima di toccare RubyGems il rilascio\nconfronta il numero scritto sull'etichetta con quello scritto dentro la libreria, e li pretende\nidentici lettera per lettera. Finora non li guardava nessuno: ",[354,675,676],{},"rake release"," pubblicava il numero\ndel gemspec qualunque cosa dicesse l'etichetta, e quando poi bundler cercava fra i tag quello che\naveva appena pubblicato non lo trovava — così se lo creava da solo. Nasceva un rilascio che nessuna\npersona aveva deciso, e il giro finiva verde. Adesso si ferma prima, e scrive quali sono i due\nnumeri che non tornano. Il confronto è fra stringhe di proposito: per le regole delle versioni Ruby\n",[354,679,680],{},"0.8"," e ",[354,683,684],{},"0.8.0"," sono lo stesso numero, ma chi legge l'annuncio di una ",[354,687,680],{}," cercherebbe su RubyGems\nuna versione che non esisterà mai.",[332,690,691,694,695,698,699,658,702,705,706,709,710,713,714,717,718,721,722,725,726,729,730,733,734,737],{},[325,692,693],{},"Hardening della supply chain CI"," (CYRB-16): le action di terze parti (",[354,696,697],{},"actions\u002Fcheckout",",\n",[354,700,701],{},"ruby\u002Fsetup-ruby",[354,703,704],{},"rubygems\u002Frelease-gem",") sono ora fissate al ",[325,707,708],{},"commit SHA"," con il tag versione a\ncommento, non più a un tag mobile che l'owner può ripuntare a un commit arbitrario; i workflow\ndichiarano permessi ",[325,711,712],{},"least-privilege"," (",[354,715,716],{},"contents: read"," di default, ",[354,719,720],{},"write"," + ",[354,723,724],{},"id-token"," solo nel\njob che pubblica); Dependabot presidia gemme di sviluppo e action tenendo i ",[325,727,728],{},"major come PR\nseparate",". Nessun impatto sul runtime della gemma (",[354,731,732],{},"concurrent-ruby"," invariato): cambia solo come la\nCI si costruisce. Un nuovo spec \"meta\" (",[354,735,736],{},"ci_hardening_spec",") impedisce di reintrodurre un riferimento\nmutabile o un token troppo ampio.",[318,739,741],{"id":740},"_080-2026-08-01","0.8.0 · 2026-08-01",[314,743,744],{},[325,745,394],{},[329,747,748],{},[332,749,750,753,754,757,758,713,763,766,767,770,771,774,775,777,778,781,782,785,786,789,790,793,794,797],{},[325,751,752],{},"Propagazione del trace context W3C"," (CYRB-15): opt-in (",[354,755,756],{},"propagate_trace_context",", default OFF) per\ncorrelare le richieste Ruby e le chiamate in uscita con lo standard\n",[567,759,762],{"href":760,"rel":761},"https:\u002F\u002Fwww.w3.org\u002FTR\u002Ftrace-context\u002F",[571],"W3C Trace Context",[354,764,765],{},"traceparent","\u002F",[354,768,769],{},"tracestate","), senza formato\nproprietario. In ",[325,772,773],{},"ingresso"," un ",[354,776,765],{}," valido diventa il ",[354,779,780],{},"trace_id"," degli eventi CloseYourIt, così\nerrore e metrica della richiesta si allineano alla traccia distribuita; un header malformato viene ignorato\ne si genera un root. In ",[325,783,784],{},"uscita"," gli header sono iniettati ",[325,787,788],{},"solo"," verso gli host di\n",[354,791,792],{},"trace_propagation_allowlist"," (default vuoto = nessuna destinazione), mai verso l'endpoint CloseYourIt né\nverso host esterni; un redirect verso un host non elencato non riceve nulla. ",[354,795,796],{},"baggage"," non viene mai emesso.",[314,799,800],{},[325,801,327],{},[329,803,804],{},[332,805,806,809,810,813,814,817,818,821,822,766,825,828,829,832,833,837,838,841,842,845,846,848,849,851,852,854,855,858,859,861,862,817,865,868,869,872,873,875],{},[325,807,808],{},"Un errore ritentato non è più segnalato una volta per tentativo"," (CYRB-19): l'",[354,811,812],{},"around_perform"," che\ncattura gli errori dei job gira ",[325,815,816],{},"dentro"," ",[354,819,820],{},"perform_now",", mentre ",[354,823,824],{},"retry_on",[354,826,827],{},"discard_on"," (rescue_from)\nsono valutati ",[325,830,831],{},"fuori",", dopo i callback — così ogni tentativo veniva segnalato come errore non gestito\n(e ogni tentativo solleva una nuova istanza, quindi la deduplica per-istanza non interviene). Un errore\npasseggero che si risolveva al secondo tentativo ne generava comunque due, gonfiando conteggi, allarmi e\ncorsa verso i limiti (sul campo: 2.033 eventi ",[834,835,836],"em",{},"rate limited",", il 74,7% erano ripetizioni di retry). Su\nActiveJob ",[325,839,840],{},"7.1+"," la segnalazione passa ad ",[354,843,844],{},"after_discard",", invocato da Rails al fallimento definitivo,\nmai sui tentativi che ",[354,847,824],{}," ritenta: un ",[354,850,824],{}," riuscito non produce errori, un ",[354,853,824],{},"\nesaurito produce ",[325,856,857],{},"una sola"," occorrenza — con i breadcrumb e i tag raccolti durante l'esecuzione\npreservati nel report. Sulle versioni prive di ",[354,860,844],{}," resta il comportamento precedente (fallback\nlegacy). Due conseguenze da conoscere: gli errori intercettati da un ",[354,863,864],{},"rescue_from",[325,866,867],{},"custom"," non sono più\nsegnalati (sono gestiti dall'app: prima li marcavamo impropriamente come non gestiti); i retry a livello\ndi ",[325,870,871],{},"adapter"," (es. Sidekiq) senza ",[354,874,824],{}," risollevano l'errore non gestito e restano quindi segnalati\na ogni esecuzione, come prima.",[318,877,879],{"id":878},"_070-2026-07-30","0.7.0 · 2026-07-30",[314,881,882],{},[325,883,394],{},[329,885,886,953,1002,1010,1051,1073],{},[332,887,888,891,892,895,896,899,900,903,904,907,908,911,912,915,916,658,919,658,921,924,925,681,928,713,930,766,933,936,937,940,941,944,945,948,949,952],{},[325,889,890],{},"Metriche dei background job"," (CYRB-14): ",[354,893,894],{},"slow_job"," (durata del ",[354,897,898],{},"perform"," oltre soglia) e\n",[354,901,902],{},"job_queue_latency"," (attesa enqueue→esecuzione oltre soglia) per ActiveJob e Sidekiq, come metriche\n",[354,905,906],{},"performance_issue",". Ogni metrica porta ",[354,909,910],{},"label"," (nome della classe del job — ",[325,913,914],{},"mai"," gli argomenti),\n",[354,917,918],{},"queue",[354,920,871],{},[354,922,923],{},"attempt"," (i retry diventano visibili), ",[354,926,927],{},"release",[354,929,780],{},[354,931,932],{},"job_id",[354,934,935],{},"jid","),\ncosì log ed errore dello stesso job si correlano. Nuove opzioni ",[354,938,939],{},"monitor_jobs"," (ON di default:\nvedere i job lenti non deve richiedere strumentazione manuale in ogni app), ",[354,942,943],{},"slow_job_threshold_ms","\n(5000), ",[354,946,947],{},"job_queue_latency_threshold_ms"," (60000), ",[354,950,951],{},"jobs_sample_rate"," (1.0). Il middleware Sidekiq\nri-solleva sempre gli errori del job ospite: la telemetria è isolata.",[332,954,955,962,963,966,967,658,970,658,973,658,976,698,979,982,983,986,987,990,991,994,995,998,999,357],{},[325,956,957,958,961],{},"Hook diagnostico ",[354,959,960],{},"on_diagnostic"," + contatori estesi"," (CYRB-12): ",[354,964,965],{},"->(event, details)"," opt-in,\ninvocato a ogni tappa del ciclo di vita di un evento (",[354,968,969],{},":enqueue",[354,971,972],{},":send",[354,974,975],{},":drop",[354,977,978],{},":timeout",[354,980,981],{},":shutdown",") con dettagli privi di dati sensibili. È ",[325,984,985],{},"locale e non ricorsivo",": non invia\ntelemetria, quindi non può innescare un loop di auto-monitoraggio. Nuovo contatore ",[354,988,989],{},"timeout"," (come\nsotto-conteggio di ",[354,992,993],{},"failed",") e alias ",[354,996,997],{},"snapshot"," su ",[354,1000,1001],{},"Stats",[332,1003,1004,1009],{},[325,1005,1006],{},[354,1007,1008],{},"CloseYourIt.after_fork"," (CYRB-11): hook per i worker dei server che precaricano l'app.",[332,1011,1012,1018,1019,1022,1023,1026,1027,1030,1031,1034,1035,1038,1039,1042,1043,1046,1047,1050],{},[325,1013,1014,1015],{},"Config ",[354,1016,1017],{},"excluded_log_patterns"," (default ",[354,1020,1021],{},"[]","): righe del broadcast ",[354,1024,1025],{},"Rails.logger"," da scartare in\nbase al ",[325,1028,1029],{},"testo",", per il rumore ripetuto che non è un'eccezione e che quindi ",[354,1032,1033],{},"excluded_exceptions","\nnon può coprire (es. ",[354,1036,1037],{},"\u002FSolidQueue-[\\d.]+ Error in thread\u002F","). I ",[354,1040,1041],{},"Regexp"," valgono come pattern, le\n",[354,1044,1045],{},"String"," come testo letterale (vengono escapate: chi scrive ",[354,1048,1049],{},"\"Error in thread (0.0ms)\""," non si\naspetta che parentesi e punto siano metacaratteri).",[332,1052,1053,1059,1060,721,1062,1064,1065,1068,1069,1072],{},[325,1054,1055,1056],{},"Predicato pubblico ",[354,1057,1058],{},"CloseYourIt.ignored_log_message?(text)",": risponde se una riga di log va\nscartata secondo ",[354,1061,1033],{},[354,1063,1017],{},". Reso pubblico per lo stesso motivo\ndi ",[354,1066,1067],{},"logs_active?"," — serve a un collaboratore (",[354,1070,1071],{},"LogBroadcast",") per non fare lavoro inutile.",[332,1074,1075,1080,1081,1084,1085,1088,1089,658,1092,658,1095,1098,1099,1102,1103,1106,1107,1109,1110,1113,1114,1117,1118,1121,1122,1125],{},[325,1076,1014,1077],{},[354,1078,1079],{},"excluded_query_patterns"," (CYRB-18): query da ",[325,1082,1083],{},"non"," misurare come rallentamento, match\nsul testo SQL. Default ",[325,1086,1087],{},"non vuoto",": ",[354,1090,1091],{},"solid_queue_",[354,1093,1094],{},"solid_cache_",[354,1096,1097],{},"solid_cable_",". Le tabelle di\nservizio del Solid stack sono infrastruttura del framework — una loro query lenta non si corregge\nleggendo il proprio repo, dice solo che il database è in contesa (cosa che le query dell'app\nraccontano già), e in compenso sommerge il segnale utile: su closeyourit-rails il 2026-07-30 erano\ncirca ",[325,1100,1101],{},"2.740 campioni su 4.400 (62%)",", tutti fra i 250 e i 655 ms. Chi vuole misurarle azzera la\nlista. ",[354,1104,1105],{},"\\b"," in testa a ogni pattern: una tabella dell'app che contenga ",[354,1108,918],{}," nel nome non sparisce\nper assonanza.",[1111,1112],"br",{},"Il filtro vale solo per la ",[325,1115,1116],{},"misura",", non per ",[354,1119,1120],{},"#breadcrumb"," né per ",[354,1123,1124],{},"#profile",": la cronologia «quali\nquery prima del crash» resta completa (nasconderne un pezzo la renderebbe bugiarda) e il profiling\nN+1 continua a vedere tutto, perché lì una tabella di servizio letta molte volte è essa stessa un\nsintomo. Un rallentamento va misurato se qualcuno può intervenire; una breadcrumb va tenuta se aiuta\na capire — due domande diverse.",[314,1127,1128],{},[325,1129,327],{},[329,1131,1132,1162,1191,1222,1250,1303],{},[332,1133,1134,1137,1138,1141,1142,1145,1146,1149,1150,1153,1154,1157,1158,1161],{},[325,1135,1136],{},"La gemma riparte nel processo figlio dopo un fork"," (CYRB-11): i server che precaricano l'app (Puma\ncluster, Sidekiq, Unicorn) inizializzano la gemma nel master e poi forkano. Il worker pool e il\n",[354,1139,1140],{},"TimerTask"," del buffer sono ",[325,1143,1144],{},"thread",", e i thread non sopravvivono al fork: nel figlio ",[354,1147,1148],{},"@client"," e\n",[354,1151,1152],{},"@log_buffer"," erano ereditati ma ",[325,1155,1156],{},"inerti",", e nessun evento partiva più. Ora il cambio di PID viene\nrilevato (lazy, al primo accesso) e le risorse ricreate nel processo corrente. I riferimenti\nereditati vengono abbandonati ",[325,1159,1160],{},"senza"," shutdown né drain: nessun join sui thread del padre, e\nnessun flush del suo buffer — rispedirebbe eventi che non sono di questo processo.",[332,1163,1164,1167,1168,1171,1172,1149,1174,1176,1177,1179,1180,1183,1184,1186,1187,1190],{},[325,1165,1166],{},"Re-inizializzare non perde più gli eventi in coda"," (CYRB-10): ",[354,1169,1170],{},"init"," azzerava ",[354,1173,1148],{},[354,1175,1152],{}," senza spegnerli, lasciando orfani il thread del worker pool e il ",[354,1178,1140],{},"; gli\neventi accodati venivano persi, o flushati fuori tempo con la ",[325,1181,1182],{},"vecchia"," credenziale. Ora ",[354,1185,1170],{},"\napplica al client precedente la semantica di fine-vita di ",[354,1188,1189],{},"#shutdown"," (flush del buffer → drain del\nworker con timeout) prima di sostituirlo. Idempotente.",[332,1192,1193,1196,1197,1200,1201,1203,1204,1210,1211,1214,1215,1218,1219,1221],{},[325,1194,1195],{},"La gemma si installa davvero su Ruby 4.0"," (CYRB-13): la CI la provava solo dentro il proprio\nbundle, dove le stdlib estratte e ",[354,1198,1199],{},"rack"," arrivano da altre gemme — un'app reale che installava solo\n",[354,1202,47],{}," su Ruby 4.0 ",[325,1205,1206,1207],{},"falliva il ",[354,1208,1209],{},"require",". Il gemspec ora dichiara ",[354,1212,1213],{},"logger"," (da Ruby\n4.0 non è più una default gem) e ",[354,1216,1217],{},"rack\u002Futils"," è caricato lazy dentro il middleware, così il require\ndella gemma non forza ",[354,1220,1199],{}," nelle app non-web.",[332,1223,1224,1227,1228,1231,1232,1235,1236,1238,1239,1242,1243,1246,1247,1249],{},[325,1225,1226],{},"Nessun batch di log perso in silenzio"," (CYRB-12): i log scartati da ",[354,1229,1230],{},"before_send"," incrementano\n",[354,1233,1234],{},"dropped"," ed emettono ",[354,1237,975],{}," come già faceva ",[354,1240,1241],{},"capture_event",", e un batch perso perché ",[354,1244,1245],{},"flush_logs","\nsolleva viene contabilizzato invece di svanire. ",[354,1248,981],{}," viene emesso una sola volta per sessione.",[332,1251,1252,1260,1261,1264,1265,1268,1269,1272,1273,1276,1277,1279,1280,1283,1284,1287,1288,1291,1292,1295,1296,1298,1299,1302],{},[325,1253,1254,1255,1257,1258],{},"Il broadcast di ",[354,1256,1025],{}," rispetta ",[354,1259,1033],{}," (CYRB-17): un'eccezione esclusa dal\ncanale ",[325,1262,1263],{},"errori"," rientrava da quello dei ",[325,1266,1267],{},"log",". Rails la registra comunque con ",[354,1270,1271],{},"logger.error",", e\n",[354,1274,1275],{},"LogBroadcast#add"," inoltrava la riga senza guardarne il testo — così il rumore che\n",[354,1278,1033],{}," aveva appena scartato ricompariva come log-entry. Misurato sul backend il\n2026-07-30: ",[325,1281,1282],{},"48.000 voci su 49.985"," nello stream cross-app, quasi tutte\n",[354,1285,1286],{},"ActionController::RoutingError"," da favicon mancanti e scansioni di bot, cioè una classe presente\nnelle esclusioni di ",[325,1289,1290],{},"default"," dalla prima riga della gemma. Il filtro guarda il testo (qui la\nclasse arriva come stringa dentro il messaggio, non come oggetto con ",[354,1293,1294],{},"ancestors",") e vive\nesclusivamente in ",[354,1297,1071],{},": un ",[354,1300,1301],{},"CloseYourIt.log"," scritto di proposito dallo sviluppatore non\nviene mai silenziato, perché chi lo scrive ha già deciso che vuole quella riga.",[332,1304,1305,1311,1312,1315,1316,1319,1320,1323],{},[325,1306,1307,1308],{},"Il filtro copre anche la forma lazy ",[354,1309,1310],{},"logger.error { ... }",": il testo viene valutato ",[325,1313,1314],{},"dopo"," lo\n",[354,1317,1318],{},"yield",". Guardando solo l'argomento posizionale (che in quella forma è ",[354,1321,1322],{},"nil",") ogni riga costruita\nlazy avrebbe scavalcato le esclusioni.",[314,1325,1326],{},[325,1327,1328],{},"Interno",[329,1330,1331,1363,1375,1392],{},[332,1332,1333,1336,1337,1340,1343,1344,1347,1348,1351,1352,1355,1356,1358,1359,1362],{},[325,1334,1335],{},"La CI verifica la gemma su una matrice Ruby con smoke install isolato"," (CYRB-13): minima ",[325,1338,1339],{},"esatta",[354,1341,1342],{},"4.0.0"," (prima ",[354,1345,1346],{},"\"4.0\""," installava l'ultima patch, lasciando la minima dichiarata non testata) più la\ncorrente derivata da ",[354,1349,1350],{},".ruby-version",", così la matrice non diverge dal runtime. Nuovo step che\ncostruisce la gemma e la installa in un ",[354,1353,1354],{},"GEM_HOME"," isolato verificando ",[354,1357,1209],{},", config no-op e API\npubblica; la release dipende da questo gate su ",[325,1360,1361],{},"tutte"," le versioni.",[332,1364,1365,1368,1369,1371,1372,357],{},[325,1366,1367],{},"Gate di branch coverage a 90"," (CYRB-13): la sola line coverage (97%) mascherava rami difensivi mai\nesercitati — guardie no-op da client disabilitato, path ",[354,1370,1322],{},", percorsi d'errore del transport.\nPortata da 84,5% a 90,7% e resa vincolante con ",[354,1373,1374],{},"COVERAGE_ENFORCE=1",[332,1376,1377,1378,1380,1381,1384,1385,998,1388,1391],{},"Chiusi due rami mai esercitati di ",[354,1379,1275],{}," (forma con block, messaggio assente): la branch\ncoverage torna sopra il gate (",[325,1382,1383],{},"90,05%","), che si era riabbassato a ",[325,1386,1387],{},"89,72%",[354,1389,1390],{},"main"," dopo\nCYRB-14.",[332,1393,1394,1088,1397,1400,1401,1404,1405,817,1407,1410,1411,1414,1415,1418,1419,1422,1423,1425,1426,1429,1430,1432,1433,1436],{},[325,1395,1396],{},"Uno spec di CYRB-14 passava solo dentro un git worktree",[354,1398,1399],{},"omette i campi nil"," faceva\n",[354,1402,1403],{},"config.release = nil",", ma il reader ",[354,1406,927],{},[325,1408,1409],{},"auto-rileva"," (tag, ENV di deploy, ",[354,1412,1413],{},"git rev-parse",").\n",[354,1416,1417],{},"git_revision"," si autoesclude quando ",[354,1420,1421],{},".git"," non è una directory — vero in un worktree, dove ",[354,1424,1421],{}," è\nun file, ",[325,1427,1428],{},"falso"," in un checkout normale come quello di ",[354,1431,697],{},": lì ",[354,1434,1435],{},"detect_release","\nrestituiva lo short SHA e lo spec cadeva. Ora stubba il reader, perché quello che vuole verificare è\nl'assenza della release, non il modo in cui viene rilevata. Trovato preparando questa release: la CI\nnon aveva mai girato su quei commit, mai pushati.",[318,1438,1440],{"id":1439},"_061-2026-07-11","0.6.1 · 2026-07-11",[314,1442,1443],{},[325,1444,327],{},[329,1446,1447],{},[332,1448,1449,1454,1455,1457,1458,766,1461,766,1464,766,1467,1470,1471,766,1474,1476,1477,1480,1481,1484,1485,1487,1488,1491,1492,1495,1496,1499,1500,1503],{},[325,1450,1451,1453],{},[354,1452,1435],{}," preferisce il tag semver allo short SHA"," (CYRB-9): l'auto-rilevamento della\n",[354,1456,927],{}," usava solo le fonti SHA (",[354,1459,1460],{},"KAMAL_VERSION",[354,1462,1463],{},"GIT_SHA",[354,1465,1466],{},"GIT_REVISION",[354,1468,1469],{},"SOURCE_VERSION","\u002F\n",[354,1472,1473],{},"HEROKU_SLUG_COMMIT",[354,1475,1413],{},"), quindi allegava agli eventi il commit hash (es. ",[354,1478,1479],{},"d3ce2af",")\ninvece del tag semver (es. ",[354,1482,1483],{},"v0.0.43","), creando release duplicate lato backend che non convergevano\ncon quelle registrate dalla CI (che usa il tag). Ora ",[354,1486,1435],{}," legge prima un tag semver da\n",[354,1489,1490],{},"APP_GIT_TAG"," poi ",[354,1493,1494],{},"GIT_TAG"," (accettato solo se non-blank e con forma ",[354,1497,1498],{},"vX.Y.Z"," + eventuale suffisso\nprerelease\u002Fbuild), con le fonti SHA come fallback invariato. Valori non-semver (",[354,1501,1502],{},"unknown",", vuoto,\nnomi di branch) vengono ignorati.",[318,1505,1507],{"id":1506},"_060-2026-07-10","0.6.0 · 2026-07-10",[314,1509,1510],{},[325,1511,394],{},[329,1513,1514],{},[332,1515,1516,1018,1521,1524,1525,1528,1529,1532,1533,1535,1536,1539,1540,1543,1544,1547],{},[325,1517,1014,1518],{},[354,1519,1520],{},"trap_signals",[354,1522,1523],{},"false",", opt-in): quando attiva, ",[354,1526,1527],{},"CloseYourIt.init"," intercetta\n",[354,1530,1531],{},"SIGTERM"," e lo converte in un exit pulito, così il flush di fine-vita gira anche al deploy (Kamal\ninvia ",[354,1534,1531],{},", che di default salta gli ",[354,1537,1538],{},"at_exit","). Opt-in perché sovrascrive un eventuale handler\n",[354,1541,1542],{},"TERM"," dell'app ospite. Esposto anche il metodo pubblico ",[354,1545,1546],{},"CloseYourIt.shutdown"," per drenare a mano.",[314,1549,1550],{},[325,1551,327],{},[329,1553,1554,1608,1637,1665,1683,1700],{},[332,1555,1556,1562,1563,1565,1566,1018,1569,1572,1573,658,1576,1579,1580,1585,1586,1589,1590,1592,1593,1595,1596,1598,1599,766,1601,1604,1605,1607],{},[325,1557,1558,1561],{},[354,1559,1560],{},"capture_rails_logs"," non inonda più lo stream col rumore del framework"," (CYRB-7): il broadcast di\n",[354,1564,1025],{}," usava ",[354,1567,1568],{},"logs_min_level",[354,1570,1571],{},":info",") come soglia → in produzione ad alto traffico\nogni riga info del framework (",[354,1574,1575],{},"Started GET",[354,1577,1578],{},"Rendered",", ...) veniva inoltrata, saturando lo stream.\nOra la soglia del broadcast è governata dalla nuova opzione ",[325,1581,1582],{},[354,1583,1584],{},"capture_rails_logs_min_level"," (default\n",[354,1587,1588],{},":warn",", distinta da ",[354,1591,1568],{},"): il rumore info del framework resta fuori di default, chi lo\nvuole abbassa esplicitamente la soglia (es. ",[354,1594,1571],{},"). ",[354,1597,1568],{}," continua a governare\n",[354,1600,1301],{},[354,1602,1603],{},".logger",". Il README già prometteva la soglia ",[354,1606,1588],{}," ma il codice non la applicava.",[332,1609,1610,1613,1614,713,1617,1620,1621,1624,1625,1627,1628,1631,1632,1634,1635,357],{},[325,1611,1612],{},"Flush di fine-vita affidabile (CYRB-5)",": allo shutdown del processo il buffer log ora ",[325,1615,1616],{},"drena\nanche il worker asincrono",[354,1618,1619],{},"@client.shutdown"," → ",[354,1622,1623],{},"wait_for_termination",") dopo il flush, non solo\naccoda l'ultimo batch. Prima l'",[354,1626,1538],{}," flushava il buffer nel worker pool ma non attendeva\nl'invio: i log sotto-batch (\u003C ",[354,1629,1630],{},"logs_batch_size",", timer non ancora scattato) restavano in coda e\nvenivano persi alla terminazione. Vedi anche la nuova config ",[354,1633,1520],{}," per il caso ",[354,1636,1531],{},[332,1638,1639,1642,1643,1646,1647,1650,1651,766,1654,766,1657,1660,1661,1664],{},[325,1640,1641],{},"Denylist Scrubber allineata alla PII del backend"," (CYRB-3): la ",[354,1644,1645],{},"DENYLIST"," dello Scrubber era più\nstretta del regex ",[354,1648,1649],{},"SENSITIVE_KEY"," del backend\u002FDart — i bind di query e metodi lenti su colonne\n",[354,1652,1653],{},"email",[354,1655,1656],{},"phone",[354,1658,1659],{},"dob"," (e affini) NON venivano redatti e finivano nel pannello \"Parametri\" della\nmetric-group, visibili a ogni viewer. Aggiunti i token ",[354,1662,1663],{},"email phone telephone mobile dob birth passport bearer session pin pan","; il match per sottostringa privilegia l'over-redaction\n(privacy-by-default).",[332,1666,1667,1675,1676,1679,1680,1682],{},[325,1668,1669,1672,1673],{},[354,1670,1671],{},"capture_message"," ora emette ",[354,1674,780],{}," (parità con ",[354,1677,1678],{},"capture_exception","): i messaggi diagnostici\nsi correlano ai log\u002Ferrori della stessa richiesta come gli eventi d'errore (prima il ",[354,1681,780],{}," era\nomesso e i messaggi restavano scollegati).",[332,1684,1685,1688,1689,1691,1692,1695,1696,1699],{},[325,1686,1687],{},"Sicurezza redirect",": il ",[354,1690,548],{}," (segreto d'ingest) non viene più ri-inviato dopo un redirect verso\nun host diverso, né su un downgrade ",[354,1693,1694],{},"https→http"," — solo stesso host (o variante ",[354,1697,1698],{},"www",") e schema non\ndegradato. Evita di consegnare il token a un endpoint non fidato.",[332,1701,1702,1705,1706,1709,1710,1713],{},[325,1703,1704],{},"DX diagnostica",": su risposta non-2xx il log include ora il codice d'errore ",[354,1707,1708],{},"R…"," e il messaggio\ndall'envelope del backend (es. ",[354,1711,1712],{},"HTTP 422 R422-INGEST-001: Evento malformato","), non solo lo status.",[318,1715,1717],{"id":1716},"_050-2026-07-08","0.5.0 · 2026-07-08",[314,1719,1720],{},[325,1721,394],{},[329,1723,1724],{},[332,1725,1726,1729,1730,1733,1734,1737,1738,1741,1742,1745,1746,766,1749,1752],{},[325,1727,1728],{},"Correlazione errore server ↔ session replay",": il middleware ",[354,1731,1732],{},"RequestContext"," legge il cookie\n",[354,1735,1736],{},"cyi_replay"," (id opaco scritto dal browser SDK) e lo mette su ",[354,1739,1740],{},"Scope#replay_session_id","; l'evento\nd'errore lo emette in ",[354,1743,1744],{},"contexts.replay.replay_id"," (stesso punto del percorso JS) → il backend lega\nil 500 al video della sessione. ",[354,1747,1748],{},"replay",[354,1750,1751],{},"replay_id"," non sono chiavi sensibili (sopravvivono allo\nScrubber). Nessuna nuova config.",[318,1754,1756],{"id":1755},"_040-2026-07-02","0.4.0 · 2026-07-02",[314,1758,1759],{},[325,1760,394],{},[329,1762,1763,1791],{},[332,1764,1765,1768,1769,766,1772,766,1775,1778,1779,1782,1783,1786,1787,1790],{},[325,1766,1767],{},"Context lines nei frame dello stacktrace",": ogni frame con file sorgente leggibile porta\n",[354,1770,1771],{},"pre_context",[354,1773,1774],{},"context_line",[354,1776,1777],{},"post_context"," (config ",[354,1780,1781],{},"context_lines",", default 3, ",[354,1784,1785],{},"0"," disattiva;\n",[354,1788,1789],{},"LineCache"," bounded e thread-safe). L'error show del backend renderizza già lo snippet.",[332,1792,1793,1800,1801,1804,1805,1808,1809,1812,1813,1816,1817,1820],{},[325,1794,1795,1796,1799],{},"Body della richiesta nell'evento (",[354,1797,1798],{},"request.data",")",": estratto LAZY solo quando l'errore accade\n(mai sul percorso felice) — preferisce i params già parsati da Rails\u002FRack, fallback rilettura\n",[354,1802,1803],{},"rack.input"," con rewind (JSON\u002Fform, cap 64 KB). Sanitizzato (upload → ",[354,1806,1807],{},"[FILE: …]",", oggetti →\n",[354,1810,1811],{},"[OBJECT: …]",", stringhe troncate a 1024) e scrubbato (denylist + ",[354,1814,1815],{},"filter_parameters","); il backend\nri-scruba difensivamente. Config ",[354,1818,1819],{},"capture_request_body"," (default true).",[318,1822,1824],{"id":1823},"_034-2026-06-29","0.3.4 · 2026-06-29",[314,1826,1827],{},[325,1828,394],{},[329,1830,1831],{},[332,1832,1833,1836,1837,1840,1841,1844,1845,1848,1849,1852,1853,1856,1857,1856,1860,1863,1864,1867,1868,1870,1871,1873,1874,1877,1878,1880,1881,357],{},[325,1834,1835],{},"Rilevamento performance issue lato client"," (opt-in ",[354,1838,1839],{},"detect_performance_issues",", default OFF):\n",[354,1842,1843],{},"Performance::RequestProfile"," accumula per-richiesta le query (per fingerprint + call-site, stile\nprosopite) e le chiamate HTTP esterne; ",[354,1846,1847],{},"Performance::Rollup"," emette verdetti ",[354,1850,1851],{},"n_plus_one"," \u002F\n",[354,1854,1855],{},"high_query_count"," \u002F ",[354,1858,1859],{},"slow_request",[354,1861,1862],{},"slow_external_http"," come ",[354,1865,1866],{},"PerformanceIssueEvent","\n(kind ",[354,1869,906],{},", con ",[354,1872,780],{},") verso ",[354,1875,1876],{},"\u002Fmetrics",". ",[354,1879,780],{}," aggiunto anche a\n",[354,1882,1883],{},"SlowQueryEvent",[314,1885,1886],{},[325,1887,327],{},[329,1889,1890],{},[332,1891,1892,1897,1898,1901,1902,1905,1906,1909,1910,1912,1913,1916,1917,1919,1920,1922,1923,1926],{},[325,1893,1894,1896],{},[354,1895,1560],{}," non agganciava il broadcast"," (i log dell'app non arrivavano a CloseYourIt):\nl'initializer del railtie ",[354,1899,1900],{},"closeyourit.capture_rails_logs"," girava ",[325,1903,1904],{},"prima"," di\n",[354,1907,1908],{},"config\u002Finitializers\u002Fcloseyourit.rb"," (dove ",[354,1911,1527],{}," imposta ",[354,1914,1915],{},"capture_rails_logs = true","),\nquindi leggeva il default ",[354,1918,1523],{}," e non agganciava mai il broadcast di ",[354,1921,1025],{},". Aggiunto\n",[354,1924,1925],{},"after: :load_config_initializers"," all'initializer.",[318,1928,1930],{"id":1929},"_033-2026-06-29","0.3.3 · 2026-06-29",[314,1932,1933],{},[325,1934,327],{},[329,1936,1937,1960,1976],{},[332,1938,1939,1945,1946,1949,1950,658,1953,698,1956,1959],{},[325,1940,1941,1942],{},"Scrubber — chiavi ",[354,1943,1944],{},"pass*",": la denylist ometteva ",[354,1947,1948],{},"pass"," bare (",[354,1951,1952],{},"pass_code",[354,1954,1955],{},"passkey",[354,1957,1958],{},"passphrase",") → allineata 1:1 al regex di backend\u002FDart (parità client-side, niente leak).",[332,1961,1962,1975],{},[325,1963,1964,1965,766,1968,766,1971,1974],{},"Scope — ",[354,1966,1967],{},"tags",[354,1969,1970],{},"extra",[354,1972,1973],{},"contexts"," scrubbati client-side"," prima dell'invio: il backend non li\nri-scrubbava sugli errori, quindi era l'unica difesa contro le chiavi sensibili in quei campi.",[332,1977,1978,1985],{},[325,1979,1980,1981,1984],{},"Log — chunking del batch a ",[354,1982,1983],{},"LOGS_MAX_BATCH"," (1000)",": un flush oltre il limite del server veniva\nrigettato in blocco (413) coi log persi; ora è spezzato in più POST sequenziali.",[318,1987,1989],{"id":1988},"_032-2026-06-29","0.3.2 · 2026-06-29",[314,1991,1992],{},[325,1993,394],{},[329,1995,1996,2100],{},[332,1997,1998,2001,2002,2005,2006],{},[325,1999,2000],{},"Log strutturati"," verso l'ingest ",[354,2003,2004],{},"\u002Flogs"," di CloseYourIt:\n",[329,2007,2008,2019,2038,2054,2074],{},[332,2009,2010,2013,2014,1620,2016,575],{},[354,2011,2012],{},"CloseYourIt.log(level, message, logger:, **attributes)"," — costruisce e bufferizza una voce di log\n(livello normalizzato ai valori canonici del backend; ",[354,2015,1588],{},[354,2017,2018],{},"warning",[332,2020,2021,2024,2025,658,2028,658,2031,2034,2035,2037],{},[354,2022,2023],{},"CloseYourIt.logger"," — oggetto Logger-compatibile (",[354,2026,2027],{},"debug\u002Finfo\u002Fwarn\u002Ferror\u002Ffatal",[354,2029,2030],{},"\u003C\u003C",[354,2032,2033],{},"add",") che\ninoltra a ",[354,2036,1301],{},". Usabile come logger esplicito dell'app, anche con attributes.",[332,2039,2040,2043,2044,2046,2047,2050,2051,2053],{},[325,2041,2042],{},"Batching"," in-memory thread-safe: flush a ",[354,2045,1630],{}," (default 50), a ",[354,2048,2049],{},"logs_flush_interval","\n(default 5s) o allo shutdown (",[354,2052,1538],{},"); invio come array, fire-and-forget.",[332,2055,2056,713,2061,2064,2065,1018,2067,2069,2070,2073],{},[325,2057,2058,2059],{},"Broadcast opt-in di ",[354,2060,1025],{},[354,2062,2063],{},"config.capture_rails_logs",", default OFF): re-inoltra i log\ndell'app ≥ ",[354,2066,1568],{},[354,2068,1571],{},"). Richiede ",[354,2071,2072],{},"BroadcastLogger"," (Rails 7.1+).",[332,2075,2076,2077,658,2080,658,2083,658,2085,698,2087,658,2089,2091,2092,2095,2096,2099],{},"Opzioni: ",[354,2078,2079],{},"logs_enabled",[354,2081,2082],{},"logs_sample_rate",[354,2084,1630],{},[354,2086,2049],{},[354,2088,1560],{},[354,2090,1568],{},". Gli ",[354,2093,2094],{},"attributes"," passano dallo ",[354,2097,2098],{},"Scrubber"," (denylist PII).",[332,2101,2102,2106,2107,2109,2110,2113,2114,2117],{},[325,2103,2104],{},[354,2105,780],{}," per richiesta (",[354,2108,1732],{},"): riusa il request id di Rails\u002FRack se presente,\naltrimenti lo genera. Attaccato sia a ",[354,2111,2112],{},"LogEvent"," sia a ",[354,2115,2116],{},"ErrorEvent"," → correlazione log↔errori.",[314,2119,2120],{},[325,2121,449],{},[329,2123,2124],{},[332,2125,2126,2127,1343,2130,2132,2133,2135],{},"Il logger diagnostico interno della gemma è ora ",[354,2128,2129],{},"CloseYourIt.internal_logger",[354,2131,2023],{},");\n",[354,2134,2023],{}," è riservato al logging applicativo strutturato.",[318,2137,2139],{"id":2138},"_031-2026-06-28","0.3.1 · 2026-06-28",[314,2141,2142],{},[325,2143,327],{},[329,2145,2146],{},[332,2147,2148,2151],{},[354,2149,2150],{},"Transport",": segue fino a 2 redirect su POST preservando metodo + body (es. apex → www), così\nl'evento non si perde in silenzio quando l'host canonico risponde 301.",[318,2153,2155],{"id":2154},"_030-2026-06-28","0.3.0 · 2026-06-28",[314,2157,2158],{},[325,2159,394],{},[329,2161,2162,2179,2196,2199,2213],{},[332,2163,2164,2167,2168,658,2171,658,2173,698,2176,2178],{},[354,2165,2166],{},"CloseYourIt.stats",": contatori diagnostici thread-safe (",[354,2169,2170],{},"enqueued",[354,2172,1234],{},[354,2174,2175],{},"sent",[354,2177,993],{},") per rendere visibili i fallimenti silenziosi del trasporto fire-and-forget.",[332,2180,2181,2182,2185,2186,658,2189,658,2192,2195],{},"Il trasporto ora logga a ",[354,2183,2184],{},"warn"," le risposte HTTP non-2xx (es. ",[354,2187,2188],{},"401",[354,2190,2191],{},"404",[354,2193,2194],{},"500","),\nprima ignorate silenziosamente.",[332,2197,2198],{},"Il background worker logga e conta gli eventi scartati quando la coda async è piena.",[332,2200,2201,2204,2205,2208,2209,2212],{},[354,2202,2203],{},"validate!"," avvisa se ",[354,2206,2207],{},"project_id"," non ha forma UUID o se ",[354,2210,2211],{},"endpoint_url"," è privo di host.",[332,2214,2215,2216,2219],{},"Scansione vulnerabilità delle dipendenze con ",[354,2217,2218],{},"bundler-audit"," nella CI.",[314,2221,2222],{},[325,2223,449],{},[329,2225,2226],{},[332,2227,2228,1088,2231,2234,2235,2238],{},[354,2229,2230],{},".rubocop.yml",[354,2232,2233],{},"TargetRubyVersion"," allineato a ",[354,2236,2237],{},"4.0"," (coerente con la gemspec).",[318,2240,2242],{"id":2241},"_020-2026-06-27","0.2.0 · 2026-06-27",[329,2244,2245],{},[332,2246,2247],{},"Baseline: client di telemetria (eccezioni, query\u002Fmetodi lenti, breadcrumbs, scope,\nsampling, scrubbing PII) con integrazione Rails\u002FSidekiq e trasporto fire-and-forget.",{"title":2249,"searchDepth":19,"depth":19,"links":2250},"",[2251,2252,2253,2254,2255,2256,2257,2258,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273],{"id":320,"depth":19,"text":321},{"id":340,"depth":19,"text":341},{"id":388,"depth":19,"text":389},{"id":427,"depth":19,"text":428},{"id":443,"depth":19,"text":444},{"id":472,"depth":19,"text":473},{"id":522,"depth":19,"text":523},{"id":552,"depth":19,"text":553},{"id":578,"depth":19,"text":579},{"id":597,"depth":19,"text":598},{"id":613,"depth":19,"text":614},{"id":740,"depth":19,"text":741},{"id":878,"depth":19,"text":879},{"id":1439,"depth":19,"text":1440},{"id":1506,"depth":19,"text":1507},{"id":1716,"depth":19,"text":1717},{"id":1755,"depth":19,"text":1756},{"id":1823,"depth":19,"text":1824},{"id":1929,"depth":19,"text":1930},{"id":1988,"depth":19,"text":1989},{"id":2138,"depth":19,"text":2139},{"id":2154,"depth":19,"text":2155},{"id":2241,"depth":19,"text":2242},"md",{},true,{"title":285,"description":286},"docs\u002Fchangelog-sdk-ruby","KfClTF_i3wkBhkSji0Fq0118JG2wXmvihoXOn7lRUQg",1791469658198]