<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Gabriel Abreu</title>
    <description>The latest articles on DEV Community by Gabriel Abreu (@gabbs279).</description>
    <link>https://dev.to/gabbs279</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4088779%2F3f19a571-6ba6-4964-a022-bc33296091c2.jpg</url>
      <title>DEV Community: Gabriel Abreu</title>
      <link>https://dev.to/gabbs279</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gabbs279"/>
    <language>en</language>
    <item>
      <title>RD Inteligente: What the Dominican AI Course Teaches, Asks For, and Says in the Fine Print</title>
      <dc:creator>Gabriel Abreu</dc:creator>
      <pubDate>Thu, 24 Sep 2026 23:53:19 +0000</pubDate>
      <link>https://dev.to/gabbs279/rd-inteligente-what-the-dominican-ai-course-teaches-asks-for-and-says-in-the-fine-print-2ed6</link>
      <guid>https://dev.to/gabbs279/rd-inteligente-what-the-dominican-ai-course-teaches-asks-for-and-says-in-the-fine-print-2ed6</guid>
      <description>&lt;p&gt;On Thursday, September 10, Dominican President Luis Abinader launched &lt;strong&gt;RD Inteligente&lt;/strong&gt;, the country's National Artificial Intelligence Literacy Program. The goal is to train a million Dominicans for free, and ITLA, the Instituto Tecnológico de Las Américas, runs it.&lt;/p&gt;

&lt;p&gt;I went to &lt;a href="https://rdinteligente.do" rel="noopener noreferrer"&gt;rdinteligente.do&lt;/a&gt; and read what almost nobody reads: the full program, the terms of use and the privacy policy, updated on September 15. Here's what it teaches, what it asks for when you sign up, and what the fine print says.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it teaches
&lt;/h2&gt;

&lt;p&gt;The program is a three-level ladder, and each level stands on its own: whoever stops at the first one still walks away with something.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Level 1, literacy.&lt;/strong&gt; Ten hours, the same for everyone, split into six "stops". You get a digital certificate from ITLA.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Level 2, productivity.&lt;/strong&gt; A track for your line of work, because, as the page puts it, "a nurse and a judge don't need the same thing". You leave with an applied project.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Level 3, specialization.&lt;/strong&gt; 60 to 120 hours in artificial intelligence, data science, cybersecurity or software development, with a "vendor certification".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are the six stops of level 1, with their titles translated:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What AI is and what it isn't (1.5 hours)&lt;/li&gt;
&lt;li&gt;Talking to an AI (2.5 hours)&lt;/li&gt;
&lt;li&gt;Distrusting well (1.5 hours)&lt;/li&gt;
&lt;li&gt;Your data and your privacy (1.5 hours)&lt;/li&gt;
&lt;li&gt;AI scams: defending yourself (1.5 hours)&lt;/li&gt;
&lt;li&gt;Your first real case (1.5 hours)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What I liked most: four and a half of the ten hours are about distrust. Of AI answers, of who you give your data to, and of scams. Stop 5 opens with a scene anyone recognizes: a call at 2:14 a.m., your mom's voice asking you to send money right now, and it isn't your mom. According to the page, thirty seconds of your voice is enough to clone it.&lt;/p&gt;

&lt;p&gt;At the launch, the president summed it up: "We don't want to turn a million Dominicans into programmers. We want a million Dominicans to be better at what they already know how to do." The curriculum goes that way.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it asks for
&lt;/h2&gt;

&lt;p&gt;Your cédula, the Dominican national ID, and an email address. According to the FAQ, it then asks for your date of birth, your province, your neighborhood and the track you want. No phone number, and it costs nothing: not the sign-up, not the content, not the certificate.&lt;/p&gt;

&lt;p&gt;The cédula serves two purposes, according to the program itself. One, checking against the voter roll of the Junta Central Electoral that the certificate goes to a real person. Two, one cédula per account, so nobody takes two spots. If the roll doesn't find you, you can enter your details by hand and keep going, but your file stays pending verification and they may ask for proof before issuing the certificate.&lt;/p&gt;

&lt;p&gt;There's no password. To log back in you type your cédula and get a one-time code by email. The page says it plainly: your email is the key to your account. If your email doesn't have two-step verification, now is a good time to turn it on.&lt;/p&gt;

&lt;p&gt;The level 1 certificate comes when you finish all six stops and answer every check. It's a certificate of participation: according to the terms, it "is not equivalent to an academic degree or a vendor professional certification". List it on your résumé as what it is.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the fine print says
&lt;/h2&gt;

&lt;p&gt;For a privacy policy, this one is clear: it says what it keeps, who else sees it, where, and for how long. It keeps four kinds of data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What you type:&lt;/strong&gt; your cédula, your email and, optionally, the track you identify with.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What the voter roll returns when your cédula is verified:&lt;/strong&gt; full name, date of birth, sex, nationality, province and municipality. It says it doesn't receive your photo or your voting history.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your progress through the course:&lt;/strong&gt; which screens you saw, what you answered and whether you got it right, your progress and your score.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Technical data:&lt;/strong&gt; your IP address, the date and time of your visits, your browser and your operating system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the technical side, it gets several things right:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The cédula is stored encrypted. Only its last four digits are kept next to it, and not even program staff see the full number: it shows up masked, like &lt;code&gt;***-*****-5678&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;No cookies. The session lives in your browser's local storage: if you check "Remember me on this device", it lasts up to ninety days of inactivity; if you don't, it ends when you close the tab.&lt;/li&gt;
&lt;li&gt;No third-party analytics or ad cookies, and the videos are self-hosted, so watching them doesn't tell any platform what you're watching.&lt;/li&gt;
&lt;li&gt;Technical logs are kept for twelve months.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But there are three things worth knowing before you hand over your cédula:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Your data lives in the United States.&lt;/strong&gt; The platform and its database are on a server there, and by signing up you authorize that transfer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The service that verifies your cédula isn't named.&lt;/strong&gt; The policy says it receives only the cédula, to check it against the voter roll, but it doesn't say which company or institution it is. It does name the other two providers: Microsoft's Azure Front Door, which sees your IP like any network intermediary, and Google Fonts, which gets your IP when the page loads its fonts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The certificate record is forever.&lt;/strong&gt; You can ask them to delete your file at any time by writing to &lt;a href="mailto:info@rdinteligente.do"&gt;info@rdinteligente.do&lt;/a&gt; from the email you registered with, a right that Dominican data protection law (Ley 172-13) gives you. But if you already earned a certificate, the record that it was issued is kept permanently.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What doesn't add up yet
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Minors.&lt;/strong&gt; The Presidency's announcement lists high school students among the program's audiences, but the platform requires a cédula, which Dominicans get at 18. The policy admits it: in practice the platform is for adults, and if minors are ever let in, it will be through a different mechanism and with parental permission.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Level 2 hours.&lt;/strong&gt; The tracks section talks about fifteen hours after the six stops; the level ladder says 25. It adds up if they count the ten common hours, but the page doesn't say.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The level 3 vendor.&lt;/strong&gt; It promises a "vendor certification" and doesn't say which vendor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The date for the million.&lt;/strong&gt; Neither the announcement nor the site says by when.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Who I'd send it to
&lt;/h2&gt;

&lt;p&gt;My mom, my dad and my aunts and uncles, before my developer friends. Level 1 isn't for people who already use these tools every day. It's for people who could lose their savings to a cloned voice on the phone, and for them, stop 5 alone is worth the ten hours.&lt;/p&gt;

&lt;p&gt;And one warning straight from the policy: the program never asks for a password, bank details or health information. In its own words: "If any form on the site ever asks you for them, it isn't ours." When something free gets popular, copies show up, and a lookalike link on WhatsApp asking for those things isn't theirs. The site is rdinteligente.do.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sources:&lt;/strong&gt; &lt;a href="https://presidencia.gob.do/noticias/presidente-luis-abinader-lanza-programa-rd-inteligente-para-capacitar-un-millon-de" rel="noopener noreferrer"&gt;Presidency announcement, September 10, 2026&lt;/a&gt; · &lt;a href="https://rdinteligente.do/" rel="noopener noreferrer"&gt;RD Inteligente: the program and FAQ&lt;/a&gt; · &lt;a href="https://rdinteligente.do/terminos" rel="noopener noreferrer"&gt;Terms of use&lt;/a&gt; · &lt;a href="https://rdinteligente.do/privacidad" rel="noopener noreferrer"&gt;Privacy policy&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I write up the things I break and fix at &lt;a href="https://codewithgabo.com/allpost?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=rd-inteligente-what-it-teaches-and-asks-for" rel="noopener noreferrer"&gt;codewithgabo.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>privacy</category>
      <category>education</category>
      <category>news</category>
    </item>
    <item>
      <title>RD Inteligente: lo que enseña, lo que pide y lo que dice la letra pequeña</title>
      <dc:creator>Gabriel Abreu</dc:creator>
      <pubDate>Thu, 24 Sep 2026 23:52:43 +0000</pubDate>
      <link>https://dev.to/gabbs279/rd-inteligente-lo-que-ensena-lo-que-pide-y-lo-que-dice-la-letra-pequena-8ff</link>
      <guid>https://dev.to/gabbs279/rd-inteligente-lo-que-ensena-lo-que-pide-y-lo-que-dice-la-letra-pequena-8ff</guid>
      <description>&lt;p&gt;El jueves 10 de septiembre, el presidente Luis Abinader lanzó &lt;strong&gt;RD Inteligente&lt;/strong&gt;, el Programa Nacional de Alfabetización en Inteligencia Artificial. La meta es capacitar gratis a un millón de dominicanos, y lo ejecuta el ITLA.&lt;/p&gt;

&lt;p&gt;Me metí a &lt;a href="https://rdinteligente.do" rel="noopener noreferrer"&gt;rdinteligente.do&lt;/a&gt; y leí lo que casi nadie lee: el programa completo, los términos de uso y la política de privacidad, actualizada el 15 de septiembre. Esto es lo que enseña, lo que te pide para entrar y lo que dice la letra pequeña.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lo que enseña
&lt;/h2&gt;

&lt;p&gt;El programa es una escalera de tres niveles, y cada uno se sostiene solo: quien se quede en el primero ya se lleva algo.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Nivel 1, alfabetización.&lt;/strong&gt; Diez horas, iguales para todo el mundo, repartidas en seis "paradas". Deja un certificado digital del ITLA.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nivel 2, productividad.&lt;/strong&gt; Una ruta según tu oficio, porque, como dice la página, "una enfermera y un juez no necesitan lo mismo". Deja un proyecto aplicado.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nivel 3, especialización.&lt;/strong&gt; De 60 a 120 horas en inteligencia artificial, ciencia de datos, ciberseguridad o desarrollo de software, con "certificación de fabricante".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Las seis paradas del nivel 1 son estas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Qué es la IA y qué no es (1.5 horas)&lt;/li&gt;
&lt;li&gt;Hablarle a una IA (2.5 horas)&lt;/li&gt;
&lt;li&gt;Desconfiar bien (1.5 horas)&lt;/li&gt;
&lt;li&gt;Sus datos y su privacidad (1.5 horas)&lt;/li&gt;
&lt;li&gt;Engaños con IA: defenderse (1.5 horas)&lt;/li&gt;
&lt;li&gt;Su primer caso real (1.5 horas)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Lo que más me gustó: de las diez horas, cuatro y media son para desconfiar. De las respuestas de la IA, de a quién le das tus datos y de las estafas. La parada 5 abre con una escena que cualquiera reconoce: una llamada a las 2:14 de la mañana, con la voz de tu mamá pidiendo que le mandes dinero ahora mismo, y no es tu mamá. Según la página, con treinta segundos de tu voz basta para clonarla.&lt;/p&gt;

&lt;p&gt;En el lanzamiento, el presidente lo resumió así: "No queremos convertir a un millón de dominicanos en programadores. Queremos que un millón de dominicanos sean mejores en aquello que ya saben hacer". El temario va en esa dirección.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lo que te pide para entrar
&lt;/h2&gt;

&lt;p&gt;Tu cédula y un correo. Según las preguntas frecuentes, después te piden tu fecha de nacimiento, tu provincia, tu sector y la ruta que quieres seguir. No hace falta número de teléfono, y no cuesta nada: ni la inscripción, ni el contenido, ni el certificado.&lt;/p&gt;

&lt;p&gt;La cédula es para dos cosas, según el propio programa. Una, verificar contra el padrón de la Junta Central Electoral que el certificado sale a nombre de una persona real. Dos, que una cédula sea una sola cuenta, para que nadie ocupe dos cupos. Si el padrón no te encuentra, puedes llenar tus datos a mano y seguir con el curso, pero tu expediente queda pendiente de verificación y te pueden pedir una comprobación antes del certificado.&lt;/p&gt;

&lt;p&gt;No hay contraseña. Para volver a entrar escribes la cédula y te llega un código de un solo uso al correo. La página lo dice clarito: tu correo es la llave de tu cuenta. Si tu correo no tiene verificación en dos pasos, este es buen momento para ponérsela.&lt;/p&gt;

&lt;p&gt;El certificado del nivel 1 sale cuando completas las seis paradas y contestas todas las comprobaciones. Es un certificado de participación: según los términos, "no equivale a un título académico ni a una certificación profesional de fabricante". Ponlo en tu CV como lo que es.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lo que dice la letra pequeña
&lt;/h2&gt;

&lt;p&gt;Para ser una política de privacidad, esta es clara: dice qué guarda, quién más lo ve, dónde y por cuánto tiempo. Guarda cuatro cosas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lo que tú escribes:&lt;/strong&gt; cédula, correo y, si quieres, la ruta con la que te identificas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lo que devuelve el padrón al verificar tu cédula:&lt;/strong&gt; nombres y apellidos, fecha de nacimiento, sexo, nacionalidad, provincia y municipio. Dice que no recibe tu foto ni tu historial electoral.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tu paso por el curso:&lt;/strong&gt; qué pantallas viste, qué respondiste y si acertaste, tu avance y tu puntaje.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Datos técnicos:&lt;/strong&gt; tu IP, la fecha y hora de tus accesos, tu navegador y tu sistema operativo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En lo técnico, hace varias cosas bien:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;La cédula se guarda cifrada. Junto a ella solo se conservan los últimos cuatro dígitos, y ni el personal del programa ve el número completo: le sale enmascarado, como &lt;code&gt;***-*****-5678&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;No pone cookies. La sesión vive en el almacenamiento local de tu navegador: si marcas "Recordarme en este dispositivo", dura hasta noventa días sin uso; si no, se cierra con la pestaña.&lt;/li&gt;
&lt;li&gt;No usa analítica de terceros ni cookies de publicidad, y los videos están en su propio servidor, así que verlos no le avisa a ninguna plataforma qué estás mirando.&lt;/li&gt;
&lt;li&gt;Los registros técnicos se guardan doce meses.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pero hay tres cosas que conviene saber antes de dar la cédula:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Tus datos viven en Estados Unidos.&lt;/strong&gt; La plataforma y su base de datos están en un servidor allá, y al registrarte autorizas esa transferencia.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;El servicio que verifica tu cédula no tiene nombre.&lt;/strong&gt; La política dice que recibe solo la cédula, para confirmarla contra el padrón, pero no dice qué empresa o institución es. A los otros dos proveedores sí los nombra: Azure Front Door, de Microsoft, que ve tu IP como cualquier intermediario de red, y Google Fonts, que recibe tu IP cuando la página carga sus letras.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;La constancia del certificado es para siempre.&lt;/strong&gt; Puedes pedir que borren tu expediente cuando quieras, escribiendo a &lt;a href="mailto:info@rdinteligente.do"&gt;info@rdinteligente.do&lt;/a&gt; desde el correo con el que te registraste, un derecho que te reconoce la Ley 172-13. Pero si ya sacaste un certificado, la constancia de que se emitió se queda guardada de forma permanente.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Lo que no cuadra todavía
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Los menores de edad.&lt;/strong&gt; El anuncio de la Presidencia pone a los estudiantes de secundaria entre los públicos del programa, pero la plataforma exige cédula, que se saca a los 18 años. La política lo admite: en la práctica es para mayores de edad, y si un día entran los menores, será con otro mecanismo y con permiso de los padres.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Las horas del nivel 2.&lt;/strong&gt; La sección de rutas habla de quince horas después de las seis paradas; la escalera de niveles dice 25. Cuadra si cuentan las diez del tramo común, pero la página no lo aclara.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;El fabricante del nivel 3.&lt;/strong&gt; Promete "certificación de fabricante" y no dice de cuál.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;La fecha del millón.&lt;/strong&gt; Ni el anuncio ni la página dicen para cuándo.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A quién se lo mandaría
&lt;/h2&gt;

&lt;p&gt;A mi mamá, a mi papá y a mis tíos, antes que a mis panas programadores. El nivel 1 no es para quien ya usa estas herramientas todos los días. Es para la gente que puede perder sus ahorros con una voz clonada en el teléfono, y para esa gente la parada 5 sola ya vale las diez horas.&lt;/p&gt;

&lt;p&gt;Y un aviso que sale de la propia política: el programa nunca pide contraseña, ni datos bancarios, ni información de salud. Lo dice así: "Si algún formulario del sitio se los pide alguna vez, no es nuestro". Cuando algo gratis se pone de moda salen las copias, y un link parecido que te llegue por WhatsApp pidiéndote esas cosas no es de ellos. El sitio es rdinteligente.do.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fuentes:&lt;/strong&gt; &lt;a href="https://presidencia.gob.do/noticias/presidente-luis-abinader-lanza-programa-rd-inteligente-para-capacitar-un-millon-de" rel="noopener noreferrer"&gt;Anuncio de la Presidencia, 10 de septiembre de 2026&lt;/a&gt; · &lt;a href="https://rdinteligente.do/" rel="noopener noreferrer"&gt;RD Inteligente: el programa y las preguntas frecuentes&lt;/a&gt; · &lt;a href="https://rdinteligente.do/terminos" rel="noopener noreferrer"&gt;Términos de uso&lt;/a&gt; · &lt;a href="https://rdinteligente.do/privacidad" rel="noopener noreferrer"&gt;Política de privacidad&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I write up the things I break and fix at &lt;a href="https://codewithgabo.com/allpost?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=rd-inteligente-lo-que-ensena-y-lo-que-pide" rel="noopener noreferrer"&gt;codewithgabo.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>privacy</category>
      <category>education</category>
      <category>news</category>
    </item>
    <item>
      <title>The AI Fixed the Bug and Broke Everything Else: How I Review What an Agent Changes</title>
      <dc:creator>Gabriel Abreu</dc:creator>
      <pubDate>Thu, 24 Sep 2026 23:52:08 +0000</pubDate>
      <link>https://dev.to/gabbs279/the-ai-fixed-the-bug-and-broke-everything-else-how-i-review-what-an-agent-changes-dl2</link>
      <guid>https://dev.to/gabbs279/the-ai-fixed-the-bug-and-broke-everything-else-how-i-review-what-an-agent-changes-dl2</guid>
      <description>&lt;p&gt;This week I made an Instagram reel: I ask the AI to fix a bug, "just that one", and it replies that it's done, and that while it was at it, it renamed my variables, updated 14 dependencies, moved the login to another framework and deleted some failing tests. "You're welcome."&lt;/p&gt;

&lt;p&gt;It's an exaggerated joke, but every piece of it really happens. In Stack Overflow's 2025 survey, the top frustration with AI tools, cited by 66% of respondents, was "AI solutions that are almost right, but not quite." The second, at 45%, was that debugging AI-generated code takes more time.&lt;/p&gt;

&lt;p&gt;The test part isn't made up either. When Anthropic launched Claude 4 in May 2025, one of the improvements it announced was that the new models were 65% less likely than Sonnet 3.7 to use shortcuts or loopholes to complete a task, on the tasks most susceptible to them. If the vendor itself measures it, it happens.&lt;/p&gt;

&lt;p&gt;I code with Claude Code (&lt;a href="https://codewithgabo.com/how-i-actually-code-with-claude-code" rel="noopener noreferrer"&gt;here's how&lt;/a&gt;), and these are the five things I do so an agent doesn't hand me a "fixed" that breaks everything else.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. I ask with a scope and a way out
&lt;/h2&gt;

&lt;p&gt;"Fix the login bug" leaves the door open to anything. I ask like this: what's wrong, where I think it is, what not to touch, and what to do if it has to be touched. For example:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Login fails when the email has uppercase letters. Fix it in &lt;code&gt;auth/login.ts&lt;/code&gt;. Don't touch the tests or the dependencies; if you think you need to, stop and tell me why.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The last part is the important one. An agent with no way to tell you "this is bigger than what you asked for" will solve the bigger thing on its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. I look at the size before the change
&lt;/h2&gt;

&lt;p&gt;Before reading a single line, I run this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git diff &lt;span class="nt"&gt;--stat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If I asked for one bug and see thirty files, I don't read anything: I ask why. The size of the diff is the first check, and the cheapest.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. I read the tests first
&lt;/h2&gt;

&lt;p&gt;If the change touches tests, I read those before the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git diff &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="s1"&gt;'*.test.*'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A test that changed along with the code it tests is the signal I look for. Sometimes the change is right, because the behavior changed on purpose. But a test that went from failing to passing because it now expects something else, or one that disappeared, didn't fix anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. I make skipping a check visible
&lt;/h2&gt;

&lt;p&gt;This is the one that has helped me the most. The @codewithgabo reels come out of a suite I built in Remotion, and before exporting, a probe checks that the video changes every two seconds. If it sits still, the export is cancelled. There's a way out, and it's there on purpose: &lt;code&gt;"allowStatic": true&lt;/code&gt; in the piece's file. It's one line, and it shows up in the diff by name.&lt;/p&gt;

&lt;p&gt;This week, while moving two reels to a new design, the probe flagged a two-second stretch below the minimum, which is 0.6%. The short way out was that line. The agent fixed the reel instead: the closing text now writes itself by hand and gets underlined, and the stretch went up to 1.3%. I don't know if it would have taken the line on another day. What I know is that if it does, I'll see it.&lt;/p&gt;

&lt;p&gt;The same goes for any test suite:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Keep &lt;code&gt;.only&lt;/code&gt; and &lt;code&gt;.skip&lt;/code&gt; out of main.&lt;/strong&gt; Playwright and Mocha have &lt;code&gt;--forbid-only&lt;/code&gt;, Vitest rejects &lt;code&gt;.only&lt;/code&gt; in CI by default, and the ESLint plugins for Jest and Vitest ship the &lt;code&gt;no-focused-tests&lt;/code&gt; and &lt;code&gt;no-disabled-tests&lt;/code&gt; rules.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Give the tests an owner.&lt;/strong&gt; With a &lt;code&gt;CODEOWNERS&lt;/code&gt; file on GitHub and the branch rule that requires code owner review, a change to the tests folder doesn't get in without someone looking at it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Give the agent rules too.&lt;/strong&gt; In Claude Code, a &lt;code&gt;PreToolUse&lt;/code&gt; hook can block edits to certain paths, like your tests, or make it ask you first.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. I don't trust how it felt
&lt;/h2&gt;

&lt;p&gt;In July 2025, METR measured 16 experienced developers working on their own projects: with AI they took 19% longer, and afterwards they believed they had been 20% faster. In February 2026, METR published new data, with newer tools, suggesting they now do help. But METR itself said that, because of how the tasks ended up selected, the new data is "only very weak evidence," and it's changing the study's design.&lt;/p&gt;

&lt;p&gt;So we still don't really know how much it speeds us up. What did become clear is that how it feels isn't a measurement. That's why the four rules above are checks that don't depend on how it went.&lt;/p&gt;

&lt;h2&gt;
  
  
  What doesn't change
&lt;/h2&gt;

&lt;p&gt;AI writes fast, and it keeps writing better. Reviewing is still my job, and yours. The agent that "fixed" the bug by deleting the test didn't lie to you: it delivered the only thing it measured as success, a passing test.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sources:&lt;/strong&gt; &lt;a href="https://survey.stackoverflow.co/2025/ai" rel="noopener noreferrer"&gt;Stack Overflow 2025 Developer Survey, AI section&lt;/a&gt; · &lt;a href="https://www.anthropic.com/news/claude-4" rel="noopener noreferrer"&gt;Anthropic, Claude 4 launch (May 22, 2025)&lt;/a&gt; · &lt;a href="https://metr.org/blog/2025-07-10-early-2025-ai-experienced-os-dev-study/" rel="noopener noreferrer"&gt;METR, July 2025 study&lt;/a&gt; · &lt;a href="https://metr.org/blog/2026-02-24-uplift-update/" rel="noopener noreferrer"&gt;METR, February 2026 update&lt;/a&gt; · &lt;a href="https://vitest.dev/config/allowonly" rel="noopener noreferrer"&gt;Vitest: allowOnly&lt;/a&gt; · &lt;a href="https://playwright.dev/docs/api/class-testconfig#test-config-forbid-only" rel="noopener noreferrer"&gt;Playwright: forbidOnly&lt;/a&gt; · &lt;a href="https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/no-disabled-tests.md" rel="noopener noreferrer"&gt;ESLint for Jest: no-disabled-tests&lt;/a&gt; · &lt;a href="https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/no-disabled-tests.md" rel="noopener noreferrer"&gt;ESLint for Vitest: no-disabled-tests&lt;/a&gt; · &lt;a href="https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners" rel="noopener noreferrer"&gt;GitHub: CODEOWNERS&lt;/a&gt; · &lt;a href="https://code.claude.com/docs/en/hooks" rel="noopener noreferrer"&gt;Claude Code: hooks&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I write up the things I break and fix at &lt;a href="https://codewithgabo.com/allpost?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=the-ai-fixed-the-bug-and-broke-everything-else" rel="noopener noreferrer"&gt;codewithgabo.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>testing</category>
      <category>git</category>
      <category>productivity</category>
    </item>
    <item>
      <title>La IA arregló el bug y rompió lo demás: cómo reviso lo que me cambia un agente</title>
      <dc:creator>Gabriel Abreu</dc:creator>
      <pubDate>Thu, 24 Sep 2026 23:51:32 +0000</pubDate>
      <link>https://dev.to/gabbs279/la-ia-arreglo-el-bug-y-rompio-lo-demas-como-reviso-lo-que-me-cambia-un-agente-364k</link>
      <guid>https://dev.to/gabbs279/la-ia-arreglo-el-bug-y-rompio-lo-demas-como-reviso-lo-que-me-cambia-un-agente-364k</guid>
      <description>&lt;p&gt;Esta semana hice un reel para Instagram: le pido a la IA que arregle un bug, "solo ese", y me contesta que listo, que de paso renombró mis variables, actualizó 14 dependencias, pasó el login a otro framework y borró unos tests que fallaban. "De nada."&lt;/p&gt;

&lt;p&gt;Es un chiste exagerado, pero cada pedazo pasa de verdad. En la encuesta de Stack Overflow de 2025, la frustración número uno con las herramientas de IA, para el 66 % de quienes respondieron, fueron las soluciones que están "casi bien, pero no del todo". La segunda, para el 45 %, fue que depurar código generado por IA toma más tiempo.&lt;/p&gt;

&lt;p&gt;Lo de los tests tampoco es invento. Cuando Anthropic lanzó Claude 4, en mayo de 2025, una de las mejoras que anunció fue que los modelos nuevos eran 65 % menos propensos que Sonnet 3.7 a tomar atajos o aprovechar huecos para completar una tarea, en las tareas más propensas a eso. Si el propio fabricante lo mide, es porque pasa.&lt;/p&gt;

&lt;p&gt;Yo programo con Claude Code (&lt;a href="https://codewithgabo.com/como-programo-con-claude-code-flujo-real" rel="noopener noreferrer"&gt;aquí conté cómo&lt;/a&gt;), y estas son las cinco cosas que hago para que un agente no me entregue un "arreglado" que rompe todo lo demás.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Pido con alcance y con salida
&lt;/h2&gt;

&lt;p&gt;"Arregla el bug del login" deja la puerta abierta a todo. Yo pido así: qué está mal, dónde creo que está, qué no se toca y qué hacer si hace falta tocarlo. Por ejemplo:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;El login falla cuando el correo tiene mayúsculas. Arréglalo en &lt;code&gt;auth/login.ts&lt;/code&gt;. No toques los tests ni las dependencias; si crees que hace falta, para y dime por qué.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;La última parte es la importante. Un agente que no tiene cómo decirte "esto es más grande de lo que pediste" va a resolver lo grande por su cuenta.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Miro el tamaño antes que el cambio
&lt;/h2&gt;

&lt;p&gt;Antes de leer una sola línea, corro esto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git diff &lt;span class="nt"&gt;--stat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si pedí un bug y veo treinta archivos, no leo nada: pregunto por qué. El tamaño del diff es la primera prueba y la más barata.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Leo los tests primero
&lt;/h2&gt;

&lt;p&gt;Si el cambio toca tests, esos los leo antes que el código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git diff &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="s1"&gt;'*.test.*'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Un test que cambió junto con el código que prueba es la señal que busco. A veces el cambio es correcto, porque el comportamiento cambió a propósito. Pero un test que pasó de fallar a pasar porque ahora espera otra cosa, o que desapareció, no arregló nada.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Hago que saltarse una prueba se vea
&lt;/h2&gt;

&lt;p&gt;Esta es la que más me ha servido. Los reels de @codewithgabo salen de una suite que armé en Remotion, y antes de exportar, un probe revisa que el video cambie cada dos segundos. Si se queda quieto, el export se cancela. Hay una salida, y está puesta a propósito: &lt;code&gt;"allowStatic": true&lt;/code&gt; en el archivo de la pieza. Es una línea, y queda en el diff con su nombre.&lt;/p&gt;

&lt;p&gt;Esta semana, pasando dos reels a un diseño nuevo, el probe marcó un tramo de dos segundos por debajo del mínimo, que es 0.6 %. La salida corta era esa línea. El agente arregló el reel: el texto del final ahora se escribe a mano y se subraya, y el tramo subió a 1.3 %. No sé si otro día habría tomado la línea. Lo que sé es que, si la toma, la veo.&lt;/p&gt;

&lt;p&gt;Lo mismo vale para cualquier suite de tests:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Que &lt;code&gt;.only&lt;/code&gt; y &lt;code&gt;.skip&lt;/code&gt; no lleguen a main.&lt;/strong&gt; Playwright y Mocha tienen &lt;code&gt;--forbid-only&lt;/code&gt;, Vitest no deja pasar un &lt;code&gt;.only&lt;/code&gt; en CI por defecto, y los plugins de ESLint para Jest y Vitest traen las reglas &lt;code&gt;no-focused-tests&lt;/code&gt; y &lt;code&gt;no-disabled-tests&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Que los tests tengan dueño.&lt;/strong&gt; Con un archivo &lt;code&gt;CODEOWNERS&lt;/code&gt; en GitHub y la regla de rama que exige la revisión del dueño, un cambio en la carpeta de tests no entra sin que alguien lo mire.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Que el agente también tenga reglas.&lt;/strong&gt; En Claude Code, un hook &lt;code&gt;PreToolUse&lt;/code&gt; puede bloquear que edite ciertas rutas, como tus tests, o hacer que te pida permiso antes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. No me fío de cómo me sentí
&lt;/h2&gt;

&lt;p&gt;En julio de 2025, METR midió a 16 programadores con experiencia trabajando en sus propios proyectos: con IA tardaron 19 % más, y al terminar creían que habían ido 20 % más rápido. En febrero de 2026, METR publicó datos nuevos, con herramientas más recientes, que apuntan a que ahora sí ayudan. Pero el mismo METR dijo que, por cómo quedaron seleccionadas las tareas, esos datos son "evidencia muy débil", y está cambiando el diseño del estudio.&lt;/p&gt;

&lt;p&gt;O sea, todavía no sabemos bien cuánto nos acelera. Lo que sí quedó claro es que lo que uno siente no es una medida. Por eso las cuatro reglas de arriba son chequeos que no dependen de cómo me fue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lo que no cambia
&lt;/h2&gt;

&lt;p&gt;La IA escribe rápido, y cada vez escribe mejor. Revisar sigue siendo mi trabajo, y el tuyo. El agente que "arregló" el bug borrando el test no te engañó: cumplió con lo único que midió como éxito, que el test pasara.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fuentes:&lt;/strong&gt; &lt;a href="https://survey.stackoverflow.co/2025/ai" rel="noopener noreferrer"&gt;Encuesta de Stack Overflow 2025, sección de IA&lt;/a&gt; · &lt;a href="https://www.anthropic.com/news/claude-4" rel="noopener noreferrer"&gt;Anthropic, lanzamiento de Claude 4 (22 de mayo de 2025)&lt;/a&gt; · &lt;a href="https://metr.org/blog/2025-07-10-early-2025-ai-experienced-os-dev-study/" rel="noopener noreferrer"&gt;METR, estudio de julio de 2025&lt;/a&gt; · &lt;a href="https://metr.org/blog/2026-02-24-uplift-update/" rel="noopener noreferrer"&gt;METR, actualización de febrero de 2026&lt;/a&gt; · &lt;a href="https://vitest.dev/config/allowonly" rel="noopener noreferrer"&gt;Vitest: allowOnly&lt;/a&gt; · &lt;a href="https://playwright.dev/docs/api/class-testconfig#test-config-forbid-only" rel="noopener noreferrer"&gt;Playwright: forbidOnly&lt;/a&gt; · &lt;a href="https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/no-disabled-tests.md" rel="noopener noreferrer"&gt;ESLint para Jest: no-disabled-tests&lt;/a&gt; · &lt;a href="https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/no-disabled-tests.md" rel="noopener noreferrer"&gt;ESLint para Vitest: no-disabled-tests&lt;/a&gt; · &lt;a href="https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners" rel="noopener noreferrer"&gt;GitHub: CODEOWNERS&lt;/a&gt; · &lt;a href="https://code.claude.com/docs/en/hooks" rel="noopener noreferrer"&gt;Claude Code: hooks&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I write up the things I break and fix at &lt;a href="https://codewithgabo.com/allpost?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=la-ia-arreglo-el-bug-y-rompio-lo-demas" rel="noopener noreferrer"&gt;codewithgabo.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>testing</category>
      <category>git</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Generar el XML no es facturar: lo que aprendí construyendo un emisor de e-CF</title>
      <dc:creator>Gabriel Abreu</dc:creator>
      <pubDate>Tue, 22 Sep 2026 00:23:40 +0000</pubDate>
      <link>https://dev.to/gabbs279/generar-el-xml-no-es-facturar-lo-que-aprendi-construyendo-un-emisor-de-e-cf-241d</link>
      <guid>https://dev.to/gabbs279/generar-el-xml-no-es-facturar-lo-que-aprendi-construyendo-un-emisor-de-e-cf-241d</guid>
      <description>&lt;p&gt;El sábado 12 de septiembre construí un emisor de comprobantes fiscales electrónicos, los e-CF de la DGII. Arma el XML de la factura, lo firma con el certificado digital del negocio, lo valida contra el esquema oficial y te imprime la representación con su código QR. Está en mi portafolio, con &lt;a href="https://invoice-generator-orpin-nine.vercel.app" rel="noopener noreferrer"&gt;una demo&lt;/a&gt; que cualquiera puede probar.&lt;/p&gt;

&lt;p&gt;En su primera pantalla dice, con estas palabras: &lt;em&gt;"usar esta herramienta no te hace emisor electrónico"&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Esa frase no es modestia. Es lo más importante que aprendí construyéndolo, y es lo que más se confunde ahora que las fechas están encima: &lt;strong&gt;generar el XML no es facturar.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Las fechas son estas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Grandes locales y medianos:&lt;/strong&gt; desde el &lt;strong&gt;1 de noviembre&lt;/strong&gt; solo pueden emitir e-CF. Sus secuencias B valen hasta el 31 de octubre.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pequeños, micro y no clasificados:&lt;/strong&gt; el plazo para implementar vence el &lt;strong&gt;15 de noviembre&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Lo que dicen la ley y el reglamento
&lt;/h2&gt;

&lt;p&gt;La Ley 32-23 le dio a cada grupo un plazo contado desde mayo de 2023: 12 meses a los grandes contribuyentes nacionales, 24 a los grandes locales y medianos, y 36 al resto. Así se ha ido cumpliendo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Grandes nacionales:&lt;/strong&gt; su plazo venció el 15 de mayo de 2024. Sus comprobantes B se dieron por vencidos el 31 de diciembre de 2025.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Grandes locales y medianos:&lt;/strong&gt; plazo el 15 de mayo de 2025, prorrogado seis meses para quien ya había solicitado ser emisor. Solo e-CF desde el 1 de noviembre de 2026.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pequeños, micro y no clasificados:&lt;/strong&gt; plazo el 15 de mayo de 2026, prorrogado seis meses de forma automática, hasta el 15 de noviembre.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Antes de apostar a otra prórroga, conviene leer dos artículos del reglamento de la ley, el Decreto 587-24. El artículo 8 dice que la prórroga es "de carácter único" y que no puede pasar de seis meses. La de los pequeños ya se dio, y fue de seis meses exactos. El artículo 55 dice que a quien no implemente a tiempo, la DGII le considera vencidos sus comprobantes.&lt;/p&gt;

&lt;p&gt;A los dos grupos anteriores, la DGII les anunció después una fecha para dejar la serie B. A los pequeños todavía no se la ha anunciado, y eso no te da tiempo extra: el 15 de noviembre es la fecha para estar &lt;strong&gt;autorizado como emisor electrónico&lt;/strong&gt;. Según el aviso de la prórroga, quien no haya implementado queda expuesto a las sanciones del artículo 27 de la ley, que remite al Código Tributario: multas de 5 a 30 salarios mínimos por incumplir deberes formales.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lo que construí, y lo que no hace
&lt;/h2&gt;

&lt;p&gt;Mi emisor hace la parte que uno imagina cuando piensa en factura electrónica. Arma el XML de la factura de crédito fiscal (tipo 31) y de la factura de consumo (tipo 32), lo firma, lo valida y lo guarda. Cada comprobante lleva un e-NCF de 13 caracteres: una &lt;code&gt;E&lt;/code&gt;, dos dígitos de tipo y diez de secuencia, como &lt;code&gt;E310000000001&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;La parte de generar, firmar, validar e imprimir me tomó un sábado, con Claude Code al lado.&lt;/p&gt;

&lt;p&gt;Lo que no hace es enviarlo a la DGII, y eso lo cambia todo. La pregunta 1.4.12 de las preguntas frecuentes de la propia DGII lo dice sin rodeos: si Impuestos Internos no recibe el e-CF, este &lt;strong&gt;carece de validez tributaria&lt;/strong&gt;, y el receptor no puede usar el crédito fiscal.&lt;/p&gt;

&lt;p&gt;O sea, un PDF con su QR, firmado y validado, que la DGII nunca recibió, no le sirve a tu cliente para su crédito fiscal. Por eso la advertencia va en la primera pantalla y no escondida en el README.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lo que aprendí armando la parte fácil
&lt;/h2&gt;

&lt;p&gt;La parte "fácil" también tiene trampas que no salen en ningún tutorial.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Un espacio rompe el esquema de la factura de crédito fiscal.&lt;/strong&gt; Para validar un e-CF se usan los esquemas XSD que publica la DGII. El del tipo 31, la factura que se usa entre empresas, define uno de sus tipos así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;xs:simpleType&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;" IndicadorServicioTodoIncluidoType"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fíjate en el espacio antes de &lt;code&gt;Indicador&lt;/code&gt;. El resto del archivo busca ese tipo por su nombre, sin el espacio. El validador que trae Java recorta el espacio y sigue como si nada. libxml2 no lo hace. Es el motor de &lt;code&gt;xmllint&lt;/code&gt;, de &lt;code&gt;lxml&lt;/code&gt; en Python, de &lt;code&gt;DOMDocument&lt;/code&gt; en PHP y del paquete de Node que usa mi emisor, y se niega a cargar el esquema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The QName value 'IndicadorServicioTodoIncluidoType' does not resolve to a(n) type definition.
WXS schema e-CF 31 v.1.0.xsd failed to compile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Los esquemas de los tipos 32, 33, 34, 44 y 45 definen el mismo tipo sin el espacio. Hoy lo volví a comprobar contra lo que publica la DGII, y el archivo sigue igual.&lt;/p&gt;

&lt;p&gt;Y confieso algo: yo tardé en verlo. En el repo dejé escrito que el esquema usaba un tipo que nunca definía. Sí lo definía, con un espacio de más, y mi búsqueda de texto no lo encontraba por ese mismo espacio.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;El ejemplo oficial de la firma trae tres URIs mal escritas.&lt;/strong&gt; La DGII publica un documento, &lt;em&gt;Firmado de e-CF&lt;/em&gt;, con ejemplos de cómo firmar. El XML que muestra la estructura de la firma trae estas tres:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://www.w3.org/TR/2001/RECxml-c14n-20010315
http://www.w3.org/2001/04/xmldsigmore#rsa-sha256
http://www.w3.org/2000/09/xmldsig#envelope d-signature
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deberían decir &lt;code&gt;REC-xml-c14n&lt;/code&gt;, &lt;code&gt;xmldsig-more&lt;/code&gt; y &lt;code&gt;enveloped-signature&lt;/code&gt;. El ejemplo en TypeScript del mismo documento las escribe bien. Pero si armas tu firma copiando ese XML, no pasa: lo probé con &lt;code&gt;xml-crypto&lt;/code&gt;, y contesta que ese algoritmo de canonicalización &lt;em&gt;"is not supported"&lt;/em&gt;. Además, una firma inválida no es un error barato. Según la pregunta 1.4.18, si la DGII rechaza un e-CF por la firma, ese e-NCF no se puede volver a usar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;El portal le contesta 403 a un script.&lt;/strong&gt; Los esquemas se bajan del portal de la DGII. Con &lt;code&gt;curl&lt;/code&gt;, la respuesta es 403; con el User-Agent de un navegador, 200. Lo volví a probar hoy. Durante un rato di por hecho que la DGII bloqueaba las descargas automáticas, y lo escribí en el plan del proyecto. No las bloquea: filtra por User-Agent. Eso importa porque los esquemas hay que revisarlos antes de cada versión. Los de las notas de débito y de crédito cambiaron el 1 de abril de 2026, casi seis meses después que los demás.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;El riesgo de verdad no es el XML, es la secuencia.&lt;/strong&gt; Dos comprobantes no pueden llevar el mismo número, y no te puedes pasar del rango que te autorizó la DGII. En mi emisor, cada factura se guarda en un archivo que lleva su e-NCF como nombre, y se escribe así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;writeFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`datos/facturas/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;encf&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.xml`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;xml&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Con &lt;code&gt;wx&lt;/code&gt;, la escritura falla si el archivo ya existe. Cumple el mismo papel que un índice único en una base de datos: un duplicado explota en vez de pasar callado. Y el número siguiente se calcula leyendo lo que ya se emitió, no con un contador que se pueda equivocar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Emitir te obliga a recibir
&lt;/h2&gt;

&lt;p&gt;Esta fue la sorpresa grande, y es la razón de fondo por la que mi emisor no te pone al día.&lt;/p&gt;

&lt;p&gt;Uno piensa en la factura electrónica como algo que sale: tu sistema firma y manda. Pero el artículo 18 del reglamento dice que &lt;strong&gt;todo emisor electrónico será también receptor electrónico&lt;/strong&gt;. Tus proveedores que ya emiten e-CF te los van a mandar a ti, y tu sistema tiene que recibirlos, acusar recibo y aprobarlos o rechazarlos.&lt;/p&gt;

&lt;p&gt;Por eso, para certificarte con un sistema propio, la DGII te pide tres direcciones de servicios web. Una para &lt;strong&gt;recibir&lt;/strong&gt; los e-CF que te emitan. Otra para recibir las &lt;strong&gt;aprobaciones comerciales&lt;/strong&gt; de lo que tú emites. Y una de &lt;strong&gt;autenticación&lt;/strong&gt;, donde se firma un archivo "semilla" con el certificado digital y se devuelve un token. Después vienen las pruebas de datos, de simulación y de comunicación.&lt;/p&gt;

&lt;p&gt;Mi emisor solo escucha en &lt;code&gt;127.0.0.1&lt;/code&gt;, es decir, en la computadora donde corre. Lo hice así a propósito, para que el certificado digital del negocio nunca salga de esa máquina. Para certificarse, tendría que abrirle tres puertas a internet. Esa es la tensión real, y no se resuelve con un XML bien hecho.&lt;/p&gt;

&lt;h2&gt;
  
  
  Si tienes un negocio: tres caminos y una pregunta
&lt;/h2&gt;

&lt;p&gt;La DGII reconoce tres vías para emitir: un sistema de desarrollo propio, un proveedor de servicios de facturación electrónica certificado, o su Facturador Gratuito.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;El Facturador Gratuito&lt;/strong&gt; no cuesta nada y no te obliga a pasar la certificación. Está pensado para poco volumen: la DGII habla de unas 150 facturas al mes. Igual necesitas RNC, Alta NCF, acceso a la Oficina Virtual y un certificado digital para procedimientos tributarios. Ese certificado va a tu nombre o al de tu representante, no al del contador.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Un proveedor certificado&lt;/strong&gt; tiene que ofrecerte, por reglamento, el paquete completo: emitir y recibir, los acuses de recibo, las aprobaciones comerciales y el resguardo de tus comprobantes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;El desarrollo propio&lt;/strong&gt; es el camino de las tres direcciones y las pruebas de arriba. Con 55 días por delante, yo no lo empezaría hoy sin un equipo técnico detrás.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Si vas con un proveedor, hay una pregunta que vale más que la demo: &lt;strong&gt;¿quién guarda mi certificado?&lt;/strong&gt; El artículo 22 del reglamento permite dos modelos. En uno, la firma se hace en tu infraestructura y el certificado se queda contigo. En el otro, el proveedor te da su software como servicio y &lt;strong&gt;custodia tu certificado en la suya&lt;/strong&gt;. Para eso necesita una interconexión con una entidad de certificación autorizada por el INDOTEL, o un permiso del INDOTEL para firmar en nombre de otros. Ese certificado firma comprobantes a tu nombre ante la DGII. Pregunta en cuál de los dos modelos estás, y pide que te lo pongan por escrito.&lt;/p&gt;

&lt;h2&gt;
  
  
  Si eres dev
&lt;/h2&gt;

&lt;p&gt;Si te piden "hacer la factura electrónica", pregunta primero qué parte. Generar, firmar y validar el XML me tomó un sábado. Recibir, aprobar, autenticar, pasar la certificación y mantenerte al día cada vez que la DGII cambie un esquema ya es un producto.&lt;/p&gt;

&lt;p&gt;Mi emisor sigue diciendo en su primera pantalla que no te hace emisor electrónico. Después de construirlo, es la frase de la que estoy más seguro.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fuentes:&lt;/strong&gt; &lt;a href="https://dgii.gov.do/publicacionesOficiales/avisosInformativos/Documents/2026/14-26.pdf" rel="noopener noreferrer"&gt;Aviso 14-26, emisión exclusiva de e-CF&lt;/a&gt; · &lt;a href="https://dgii.gov.do/publicacionesOficiales/avisosInformativos/Documents/2026/06-26.pdf" rel="noopener noreferrer"&gt;Aviso 06-26, prórroga de pequeños, micro y no clasificados&lt;/a&gt; · &lt;a href="https://dgii.gov.do/publicacionesOficiales/avisosInformativos/Documents/2025/12-25.pdf" rel="noopener noreferrer"&gt;Aviso 12-25&lt;/a&gt; · &lt;a href="https://dgii.gov.do/publicacionesOficiales/avisosInformativos/Documents/2025/25-25.pdf" rel="noopener noreferrer"&gt;Aviso 25-25&lt;/a&gt; · &lt;a href="https://dgii.gov.do/legislacion/leyesTributarias/Documents/Otras%20Leyes%20de%20Inter%C3%A9s/32-23.pdf" rel="noopener noreferrer"&gt;Ley 32-23&lt;/a&gt; · &lt;a href="https://dgii.gov.do/legislacion/decretos/Documents/2024/Decreto587-24.pdf" rel="noopener noreferrer"&gt;Decreto 587-24&lt;/a&gt; · &lt;a href="https://dgii.gov.do/cicloContribuyente/facturacion/comprobantesFiscalesElectronicosE-CF/Preguntas%20frecuentes/Generales/Preguntas%20Frecuentes%20e-CF%20Generales.pdf" rel="noopener noreferrer"&gt;Preguntas frecuentes de e-CF&lt;/a&gt; · &lt;a href="https://dgii.gov.do/cicloContribuyente/facturacion/comprobantesFiscalesElectronicosE-CF/Preguntas%20frecuentes/Generales/Preguntas-Frecuentes-Facturador-Gratuito.pdf" rel="noopener noreferrer"&gt;Preguntas frecuentes del Facturador Gratuito&lt;/a&gt; · &lt;a href="https://dgii.gov.do/cicloContribuyente/facturacion/comprobantesFiscalesElectronicosE-CF/Paginas/documentacionSobreE-CF.aspx" rel="noopener noreferrer"&gt;Documentación técnica y esquemas XSD&lt;/a&gt; · &lt;a href="https://github.com/Gabbs27/invoice-generator" rel="noopener noreferrer"&gt;El código del emisor&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I write up the things I break and fix at &lt;a href="https://codewithgabo.com/allpost?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=generar-el-xml-no-es-facturar" rel="noopener noreferrer"&gt;codewithgabo.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>xml</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Generating the XML Isn't Invoicing: What I Learned Building a Dominican E-Invoice Issuer</title>
      <dc:creator>Gabriel Abreu</dc:creator>
      <pubDate>Tue, 22 Sep 2026 00:23:04 +0000</pubDate>
      <link>https://dev.to/gabbs279/generating-the-xml-isnt-invoicing-what-i-learned-building-a-dominican-e-invoice-issuer-26hl</link>
      <guid>https://dev.to/gabbs279/generating-the-xml-isnt-invoicing-what-i-learned-building-a-dominican-e-invoice-issuer-26hl</guid>
      <description>&lt;p&gt;On Saturday, September 12, I built an issuer of electronic fiscal receipts, the e-CF that the Dominican tax authority, the DGII, requires. It builds the invoice XML, signs it with the business's digital certificate, validates it against the official schema and prints the invoice with its QR code. It is in my portfolio, with &lt;a href="https://invoice-generator-orpin-nine.vercel.app" rel="noopener noreferrer"&gt;a demo&lt;/a&gt; anyone can try.&lt;/p&gt;

&lt;p&gt;Its first screen says, in Spanish, that using it does not make you an &lt;em&gt;emisor electrónico&lt;/em&gt;, an authorised electronic issuer.&lt;/p&gt;

&lt;p&gt;That sentence is not modesty. It is the most important thing I learned building it, and it is exactly what gets confused now that the deadlines are close: &lt;strong&gt;generating the XML is not invoicing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These are the deadlines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Large local and medium taxpayers:&lt;/strong&gt; from &lt;strong&gt;November 1&lt;/strong&gt; they can only issue e-CF. Their non-electronic "B" sequences are valid until October 31.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Small, micro and unclassified taxpayers:&lt;/strong&gt; the deadline to implement falls on &lt;strong&gt;November 15&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What the law and the regulation say
&lt;/h2&gt;

&lt;p&gt;Law 32-23 gave each group a deadline counted from May 2023: 12 months for large national taxpayers, 24 for large local and medium ones, and 36 for everyone else. This is how it has played out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Large national taxpayers:&lt;/strong&gt; their deadline was May 15, 2024. Their B receipts were declared expired on December 31, 2025.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Large local and medium taxpayers:&lt;/strong&gt; deadline May 15, 2025, extended six months for those who had already applied to become issuers. Only e-CF from November 1, 2026.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Small, micro and unclassified:&lt;/strong&gt; deadline May 15, 2026, extended six months automatically, to November 15.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before betting on another extension, it is worth reading two articles of the law's regulation, Decree 587-24. Article 8 says the extension is a one-time measure and cannot exceed six months. The small taxpayers already got theirs, and it was exactly six months. Article 55 says that for anyone who does not implement in time, the DGII treats their receipts as expired.&lt;/p&gt;

&lt;p&gt;The two earlier groups were later given a date to stop using the B series. The small ones have not been given one yet, and that buys no extra time: November 15 is the date to be &lt;strong&gt;authorised as an electronic issuer&lt;/strong&gt;. According to the extension notice, anyone who has not implemented faces the penalties in article 27 of the law, which points to the Tax Code: fines of 5 to 30 minimum wages for breaching formal duties.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built, and what it does not do
&lt;/h2&gt;

&lt;p&gt;My issuer does the part people picture when they think of e-invoicing. It builds the XML for the tax credit invoice (type 31) and the consumer invoice (type 32), signs it, validates it and stores it. Each receipt carries a 13-character e-NCF: an &lt;code&gt;E&lt;/code&gt;, two digits for the type and ten for the sequence, as in &lt;code&gt;E310000000001&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Generating, signing, validating and printing took me a Saturday, with Claude Code alongside.&lt;/p&gt;

&lt;p&gt;What it does not do is send anything to the DGII, and that changes everything. Question 1.4.12 of the DGII's own FAQ says it bluntly: if the tax authority never receives the e-CF, it &lt;strong&gt;has no tax validity&lt;/strong&gt;, and the buyer cannot claim the tax credit.&lt;/p&gt;

&lt;p&gt;In other words, a PDF with its QR code, signed and validated, that the DGII never received is useless to your customer's tax credit. That is why the warning is on the first screen and not buried in the README.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned building the easy part
&lt;/h2&gt;

&lt;p&gt;The "easy" part has traps of its own, and no tutorial mentions them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One space breaks the schema for the tax credit invoice.&lt;/strong&gt; An e-CF is validated against XSD schemas the DGII publishes. The one for type 31, the invoice businesses use with each other, defines one of its types like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;xs:simpleType&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;" IndicadorServicioTodoIncluidoType"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look at the space before &lt;code&gt;Indicador&lt;/code&gt;. The rest of the file looks the type up by its name, without the space. The validator that ships with Java trims the space and carries on. libxml2 does not. It is the engine behind &lt;code&gt;xmllint&lt;/code&gt;, &lt;code&gt;lxml&lt;/code&gt; in Python, &lt;code&gt;DOMDocument&lt;/code&gt; in PHP and the Node package my issuer uses, and it refuses to load the schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The QName value 'IndicadorServicioTodoIncluidoType' does not resolve to a(n) type definition.
WXS schema e-CF 31 v.1.0.xsd failed to compile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The schemas for types 32, 33, 34, 44 and 45 define the same type without the space. I checked again today against what the DGII publishes, and the file is unchanged.&lt;/p&gt;

&lt;p&gt;And a confession: I was slow to see it. What I wrote in the repo is that the schema used a type it never defined. It did define it, with one space too many, and my text search could not find it because of that same space.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The official signing example has three misspelled URIs.&lt;/strong&gt; The DGII publishes a document, &lt;em&gt;Firmado de e-CF&lt;/em&gt;, with examples of how to sign. The XML that shows the structure of the signature has these three:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://www.w3.org/TR/2001/RECxml-c14n-20010315
http://www.w3.org/2001/04/xmldsigmore#rsa-sha256
http://www.w3.org/2000/09/xmldsig#envelope d-signature
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They should read &lt;code&gt;REC-xml-c14n&lt;/code&gt;, &lt;code&gt;xmldsig-more&lt;/code&gt; and &lt;code&gt;enveloped-signature&lt;/code&gt;. The TypeScript example in the same document spells them correctly. But if you build your signature by copying that XML, it fails: I tried it with &lt;code&gt;xml-crypto&lt;/code&gt;, and it answers that the canonicalisation algorithm &lt;em&gt;"is not supported"&lt;/em&gt;. A bad signature is not a cheap mistake, either. According to question 1.4.18, if the DGII rejects an e-CF over its signature, that e-NCF can never be used again.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The portal answers a script with a 403.&lt;/strong&gt; The schemas are downloaded from the DGII's portal. With &lt;code&gt;curl&lt;/code&gt;, the answer is 403; with a browser's User-Agent, 200. I tried it again today. For a while I assumed the DGII blocked automated downloads, and I wrote that into the project plan. It does not block them: it filters by User-Agent. That matters because the schemas have to be checked before every release. The ones for debit and credit notes changed on April 1, 2026, almost six months after the rest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The real risk is not the XML, it is the sequence.&lt;/strong&gt; Two receipts cannot share a number, and you cannot go past the range the DGII authorised. In my issuer, each invoice is saved to a file named after its e-NCF, written like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;writeFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`datos/facturas/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;encf&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.xml`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;xml&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;code&gt;wx&lt;/code&gt;, the write fails if the file already exists. It does the job of a unique index in a database: a duplicate blows up instead of slipping through quietly. And the next number is worked out by reading what was already issued, not from a counter that can be wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  Issuing means receiving
&lt;/h2&gt;

&lt;p&gt;This was the big surprise, and it is the underlying reason my issuer does not get you compliant.&lt;/p&gt;

&lt;p&gt;You think of e-invoicing as something that goes out: your system signs and sends. But article 18 of the regulation says that &lt;strong&gt;every electronic issuer is also an electronic receiver&lt;/strong&gt;. Your suppliers who already issue e-CF will send theirs to you, and your system has to receive them, acknowledge receipt, and approve or reject them.&lt;/p&gt;

&lt;p&gt;That is why, to certify your own system, the DGII asks for three web service addresses. One to &lt;strong&gt;receive&lt;/strong&gt; the e-CF issued to you. Another to receive the &lt;strong&gt;commercial approvals&lt;/strong&gt; of what you issue. And one for &lt;strong&gt;authentication&lt;/strong&gt;, where a "seed" file is signed with the digital certificate and a token comes back. Then come the data, simulation and communication tests.&lt;/p&gt;

&lt;p&gt;My issuer only listens on &lt;code&gt;127.0.0.1&lt;/code&gt;, meaning the computer it runs on. I did that on purpose, so the business's digital certificate never leaves that machine. To be certified, it would have to open three doors to the internet. That is the real tension, and a well-formed XML does not resolve it.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you run a business: three paths and one question
&lt;/h2&gt;

&lt;p&gt;The DGII recognises three ways to issue: your own system, a certified e-invoicing service provider, or its free invoicing tool, the &lt;em&gt;Facturador Gratuito&lt;/em&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Facturador Gratuito&lt;/strong&gt; costs nothing and does not require certification. It is meant for low volume: the DGII talks about roughly 150 invoices a month. You still need a tax ID, authorisation to issue receipts, access to the DGII's online office and a digital certificate for tax procedures. That certificate goes in your name or your representative's, not your accountant's.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A certified provider&lt;/strong&gt; has to offer you, by regulation, the whole package: issuing and receiving, acknowledgements of receipt, commercial approvals and storage of your receipts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Building your own&lt;/strong&gt; is the path with the three addresses and the tests above. With 55 days left, I would not start it today without a technical team behind it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you go with a provider, there is one question worth more than the demo: &lt;strong&gt;who holds my certificate?&lt;/strong&gt; Article 22 of the regulation allows two models. In one, signing happens on your infrastructure and the certificate stays with you. In the other, the provider sells its software as a service and &lt;strong&gt;keeps your certificate on its own infrastructure&lt;/strong&gt;. For that it needs an interconnection with a certification entity authorised by INDOTEL, the Dominican telecom regulator, or an INDOTEL licence to sign on behalf of others. That certificate signs receipts in your name before the DGII. Ask which of the two models you are in, and get it in writing.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you are a developer
&lt;/h2&gt;

&lt;p&gt;If someone asks you to "do the e-invoicing", ask which part first. Generating, signing and validating the XML took me a Saturday. Receiving, approving, authenticating, passing certification and keeping up every time the DGII changes a schema is a product.&lt;/p&gt;

&lt;p&gt;My issuer still says on its first screen that it does not make you an electronic issuer. Having built it, that is the sentence I am most sure of.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sources (in Spanish):&lt;/strong&gt; &lt;a href="https://dgii.gov.do/publicacionesOficiales/avisosInformativos/Documents/2026/14-26.pdf" rel="noopener noreferrer"&gt;Notice 14-26, e-CF only&lt;/a&gt; · &lt;a href="https://dgii.gov.do/publicacionesOficiales/avisosInformativos/Documents/2026/06-26.pdf" rel="noopener noreferrer"&gt;Notice 06-26, extension for small, micro and unclassified taxpayers&lt;/a&gt; · &lt;a href="https://dgii.gov.do/publicacionesOficiales/avisosInformativos/Documents/2025/12-25.pdf" rel="noopener noreferrer"&gt;Notice 12-25&lt;/a&gt; · &lt;a href="https://dgii.gov.do/publicacionesOficiales/avisosInformativos/Documents/2025/25-25.pdf" rel="noopener noreferrer"&gt;Notice 25-25&lt;/a&gt; · &lt;a href="https://dgii.gov.do/legislacion/leyesTributarias/Documents/Otras%20Leyes%20de%20Inter%C3%A9s/32-23.pdf" rel="noopener noreferrer"&gt;Law 32-23&lt;/a&gt; · &lt;a href="https://dgii.gov.do/legislacion/decretos/Documents/2024/Decreto587-24.pdf" rel="noopener noreferrer"&gt;Decree 587-24&lt;/a&gt; · &lt;a href="https://dgii.gov.do/cicloContribuyente/facturacion/comprobantesFiscalesElectronicosE-CF/Preguntas%20frecuentes/Generales/Preguntas%20Frecuentes%20e-CF%20Generales.pdf" rel="noopener noreferrer"&gt;e-CF FAQ&lt;/a&gt; · &lt;a href="https://dgii.gov.do/cicloContribuyente/facturacion/comprobantesFiscalesElectronicosE-CF/Preguntas%20frecuentes/Generales/Preguntas-Frecuentes-Facturador-Gratuito.pdf" rel="noopener noreferrer"&gt;Facturador Gratuito FAQ&lt;/a&gt; · &lt;a href="https://dgii.gov.do/cicloContribuyente/facturacion/comprobantesFiscalesElectronicosE-CF/Paginas/documentacionSobreE-CF.aspx" rel="noopener noreferrer"&gt;Technical documentation and XSD schemas&lt;/a&gt; · &lt;a href="https://github.com/Gabbs27/invoice-generator" rel="noopener noreferrer"&gt;The issuer's code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I write up the things I break and fix at &lt;a href="https://codewithgabo.com/allpost?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=generating-the-xml-is-not-invoicing" rel="noopener noreferrer"&gt;codewithgabo.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>xml</category>
      <category>showdev</category>
    </item>
    <item>
      <title>La próxima filtración llegó en cuatro días: cómo leer lo de la Policía</title>
      <dc:creator>Gabriel Abreu</dc:creator>
      <pubDate>Thu, 17 Sep 2026 18:00:00 +0000</pubDate>
      <link>https://dev.to/gabbs279/la-proxima-filtracion-llego-en-cuatro-dias-como-leer-lo-de-la-policia-3hp</link>
      <guid>https://dev.to/gabbs279/la-proxima-filtracion-llego-en-cuatro-dias-como-leer-lo-de-la-policia-3hp</guid>
      <description>&lt;p&gt;El 15 de septiembre publiqué &lt;a href="https://codewithgabo.com/lo-de-claro-que-se-sabe-y-que-no" rel="noopener noreferrer"&gt;un análisis de lo de Claro&lt;/a&gt; con una sección titulada "cómo leer la próxima afirmación de filtración". Escribí que iba a haber otra.&lt;/p&gt;

&lt;p&gt;Llegó hoy. Cuatro días después de la de Claro.&lt;/p&gt;

&lt;p&gt;Una cuenta que monitorea canales de cibercrimen, VECERT Analyzer, publicó una alerta: alguien compartió un enlace de descarga que &lt;strong&gt;supuestamente&lt;/strong&gt; contiene registros del Sistema Policial de Gestión de Denuncias, el SPGD de la Policía Nacional. Un archivo de 10,000 líneas en una plataforma de alojamiento temporal.&lt;/p&gt;

&lt;p&gt;La misma alerta lo dice en su primera línea: &lt;strong&gt;estado, no confirmado.&lt;/strong&gt; Hay evidencia visible —el enlace existe, y quien lo publicó adjuntó el escudo de la institución— pero la autenticidad de los registros, su vigencia y el alcance de cualquier compromiso están sin verificar.&lt;/p&gt;

&lt;p&gt;Al momento de escribir esto no encontré un solo medio dominicano cubriéndolo, ni una respuesta de la Policía.&lt;/p&gt;

&lt;p&gt;Así que voy a hacer lo que dije que había que hacer: pasarle los cinco filtros, en público, sin saber de antemano qué sale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por qué esta importa más que la de Claro
&lt;/h2&gt;

&lt;p&gt;Antes de los filtros, el contexto. El SPGD no es una lista de clientes.&lt;/p&gt;

&lt;p&gt;Según la propia Policía Nacional, al sistema se migraron &lt;strong&gt;más de cuatro millones de registros&lt;/strong&gt;, y se alimenta desde más de 170 centros de recepción en todo el país. El portal público acepta denuncias oficiales, denuncias anónimas y denuncias de &lt;strong&gt;violencia de género&lt;/strong&gt;, y le pide al ciudadano sus datos personales, el relato detallado del hecho y sus datos de contacto.&lt;/p&gt;

&lt;p&gt;Ese mismo portal hace una promesa, textual: &lt;em&gt;"Se garantizará la protección de la identidad de la persona denunciante y/o de la persona afectada."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Una lista de teléfonos filtrada facilita estafas. Una base de denuncias identifica a quien denunció, a quién denunció, y qué contó. Si la alegación fuera cierta, lo que se habría roto es esa promesa exacta.&lt;/p&gt;

&lt;p&gt;Por eso este caso exige más cuidado que el anterior, no menos. Y por eso hay algo que va primero que cualquier filtro:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No busques ese archivo. No lo bajes. No lo compartas.&lt;/strong&gt; Si es falso, es un anzuelo — un archivo de origen criminal que alguien quiere que abras. Si es real, adentro hay personas que denunciaron a un agresor creyendo que nadie más lo sabría. Yo no lo descargué para escribir esto, y nada en este análisis lo necesita.&lt;/p&gt;

&lt;h2&gt;
  
  
  Filtro 1: ¿hay muestra verificable?
&lt;/h2&gt;

&lt;p&gt;Hay más que en el caso de Claro: no una captura, sino un enlace a un archivo. Pero "existe un archivo" y "el archivo es lo que dicen" son afirmaciones distintas, y nadie independiente ha verificado la segunda. La propia alerta lo reconoce.&lt;/p&gt;

&lt;p&gt;Veredicto: evidencia de que alguien publicó algo. Nada más.&lt;/p&gt;

&lt;h2&gt;
  
  
  Filtro 2: ¿los campos son internos o de catálogo?
&lt;/h2&gt;

&lt;p&gt;La alerta no dice qué campos trae el archivo. No hay esquema, no hay muestra descrita, no hay nada contra qué comparar. Este filtro es el que más separa una filtración real de un refrito, y aquí no se puede ni empezar a aplicar.&lt;/p&gt;

&lt;p&gt;Veredicto: sin datos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Filtro 3: ¿los datos son frescos?
&lt;/h2&gt;

&lt;p&gt;Tampoco se sabe. Y aquí hay una trampa específica de este sistema: como al SPGD se migraron millones de registros históricos, datos viejos no probarían que sea falso — el sistema real los contiene. Lo que haría falta para probar acceso actual son registros recientes, y nadie ha mostrado ninguno.&lt;/p&gt;

&lt;p&gt;Veredicto: sin datos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Filtro 4: ¿alguien lo cruzó con filtraciones anteriores?
&lt;/h2&gt;

&lt;p&gt;No que se haya publicado. Con una aritmética sencilla encima: 10,000 líneas contra más de cuatro millones de registros es el &lt;strong&gt;0.25%&lt;/strong&gt; del sistema. Eso puede ser una muestra para probar acceso, puede ser todo lo que alguien tiene, o puede ser un recorte de otra cosa. Las tres explicaciones producen exactamente el mismo enlace.&lt;/p&gt;

&lt;p&gt;Veredicto: sin datos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Filtro 5: ¿quién lo está contando?
&lt;/h2&gt;

&lt;p&gt;Un agregador. Que, para su crédito, etiqueta la alerta como no confirmada desde la primera línea. El riesgo viene después: cada vez que alguien la reenvíe, esa etiqueta es lo primero que se cae. "Alegada filtración, sin confirmar" se convierte en "hackearon a la Policía" en dos reenvíos.&lt;/p&gt;

&lt;p&gt;Y un detalle que vale anotar: el alias al que se atribuye esta publicación &lt;strong&gt;difiere en un carácter&lt;/strong&gt; del que los medios atribuyeron a lo de Claro. Puede ser la misma persona, un error de transcripción de alguien, o un imitador montado en el nombre del momento. Yo no lo sé, y quien te diga que sí tampoco lo sabe.&lt;/p&gt;

&lt;p&gt;Veredicto: fuente honesta sobre su propia incertidumbre. Los reenvíos no lo serán.&lt;/p&gt;

&lt;h2&gt;
  
  
  El marcador
&lt;/h2&gt;

&lt;p&gt;Cinco filtros: uno con evidencia parcial, tres sin datos, uno que describe al mensajero. &lt;strong&gt;Eso no es "falso". Es "no se sabe".&lt;/strong&gt; Y no se sabe es una respuesta completa — la única honesta hoy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué hacer si tú denunciaste algo
&lt;/h2&gt;

&lt;p&gt;Aquí el consejo no es el de Claro. No hay segundo factor que mover.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Si te llaman "de la Policía" con detalles de tu caso, eso ya no prueba nada.&lt;/strong&gt; Conocer tu denuncia no demuestra que quien llama es un agente. Si te piden dinero, datos o que vayas a algún sitio: cuelga, y verifica tú en tu destacamento o por los canales oficiales.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Si denunciaste a un agresor y esto te preocupa&lt;/strong&gt;, la Línea Mujer del Ministerio de la Mujer es el &lt;code&gt;*212&lt;/code&gt;: gratuita, confidencial, 24 horas, y se marca desde cualquier celular de Altice, Claro o Viva. No esperes a que alguien confirme nada para llamar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Y no vayas a buscar si apareces en el archivo.&lt;/strong&gt; Es la reacción natural y es exactamente la que aprovecha un anzuelo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lo que nos toca a los que construimos sistemas
&lt;/h2&gt;

&lt;p&gt;La recomendación técnica de la alerta es la parte más útil, y aplica a cualquiera: auditar los registros de acceso para identificar qué usuario o qué IP hizo consultas masivas o exportó 10,000 registros recientemente.&lt;/p&gt;

&lt;p&gt;La pregunta incómoda es si tu sistema puede responderla. ¿Queda registrado quién exporta? ¿Salta una alerta cuando una cuenta lee diez mil filas en una tarde? Un sistema con más de 170 puntos de entrada tiene más de 170 conjuntos de credenciales; la pregunta nunca es si una se va a comprometer, sino cuánto puede leer antes de que alguien lo note.&lt;/p&gt;

&lt;p&gt;Esa capacidad —poder decir en horas "sí fue nuestro" o "no lo fue"— es la misma que pedí en el post de Claro. Cuatro días después vuelve a ser la pieza que falta.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fuentes:&lt;/strong&gt; la alerta es de VECERT Analyzer, marcada como no confirmada por la propia cuenta · &lt;a href="https://www.policianacional.gob.do/policia-nacional-moderniza-certificaciones-vehiculares-y-denuncias-con-plataforma-digital/" rel="noopener noreferrer"&gt;Policía Nacional, sobre el SPGD&lt;/a&gt; · &lt;a href="https://denuncias.policia.gob.do/" rel="noopener noreferrer"&gt;Portal de denuncias&lt;/a&gt; · &lt;a href="https://mujer.gob.do/index.php/servicios/linea-mujer-212" rel="noopener noreferrer"&gt;Línea Mujer *212&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I write up the things I break and fix at &lt;a href="https://codewithgabo.com/allpost?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=la-proxima-filtracion-llego-en-cuatro-dias" rel="noopener noreferrer"&gt;codewithgabo.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>security</category>
      <category>privacy</category>
      <category>webdev</category>
      <category>cybersecurity</category>
    </item>
    <item>
      <title>The Next Leak Claim Took Four Days: Reading the Police One</title>
      <dc:creator>Gabriel Abreu</dc:creator>
      <pubDate>Thu, 17 Sep 2026 17:57:52 +0000</pubDate>
      <link>https://dev.to/gabbs279/the-next-leak-claim-took-four-days-reading-the-police-one-49mc</link>
      <guid>https://dev.to/gabbs279/the-next-leak-claim-took-four-days-reading-the-police-one-49mc</guid>
      <description>&lt;p&gt;On September 15 I published &lt;a href="https://codewithgabo.com/the-claro-claim-what-is-known-and-what-is-not" rel="noopener noreferrer"&gt;an analysis of the Claro claim&lt;/a&gt; with a section called "how to read the next leak claim." I wrote that there would be another one.&lt;/p&gt;

&lt;p&gt;It arrived today. Four days after the Claro one.&lt;/p&gt;

&lt;p&gt;An account that monitors cybercrime channels, VECERT Analyzer, published an alert: someone shared a download link that &lt;strong&gt;allegedly&lt;/strong&gt; contains records from the Dominican National Police's complaint management system, the SPGD. A 10,000-line file on a temporary hosting platform.&lt;/p&gt;

&lt;p&gt;The alert itself says it in its first line: &lt;strong&gt;status, unconfirmed.&lt;/strong&gt; There is visible evidence — the link exists, and whoever posted it attached the institution's crest — but the authenticity of the records, how current they are, and the extent of any compromise are all unverified.&lt;/p&gt;

&lt;p&gt;At the time of writing I could not find a single Dominican outlet covering it, nor a response from the Police.&lt;/p&gt;

&lt;p&gt;So I am going to do what I said should be done: run the five filters, in public, without knowing in advance what comes out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this one matters more than Claro
&lt;/h2&gt;

&lt;p&gt;Before the filters, the context. The SPGD is not a customer list.&lt;/p&gt;

&lt;p&gt;According to the National Police itself, &lt;strong&gt;more than four million records&lt;/strong&gt; were migrated into the system, and it is fed from more than 170 reception centres across the country. The public portal accepts official complaints, anonymous tips and &lt;strong&gt;gender violence&lt;/strong&gt; reports, and asks the citizen for personal data, a detailed account of what happened, and contact details.&lt;/p&gt;

&lt;p&gt;That same portal makes a promise, verbatim: &lt;em&gt;"Se garantizará la protección de la identidad de la persona denunciante y/o de la persona afectada"&lt;/em&gt; — the identity of the person reporting, and of the person affected, will be protected.&lt;/p&gt;

&lt;p&gt;A leaked phone list makes scams easier. A complaints database identifies who reported, whom they reported, and what they said. If the claim were true, that exact promise is what would have been broken.&lt;/p&gt;

&lt;p&gt;Which is why this case calls for more care than the last one, not less. And why one thing comes before any filter:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do not look for that file. Do not download it. Do not share it.&lt;/strong&gt; If it is fake, it is bait — a file of criminal origin that someone wants you to open. If it is real, inside it are people who reported an abuser believing nobody else would know. I did not download it to write this, and nothing in this analysis needs it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Filter 1: is there a verifiable sample?
&lt;/h2&gt;

&lt;p&gt;There is more than in the Claro case: not a screenshot, but a link to a file. But "a file exists" and "the file is what they say" are different claims, and no independent party has verified the second. The alert itself acknowledges that.&lt;/p&gt;

&lt;p&gt;Verdict: evidence that someone posted something. Nothing more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Filter 2: are the fields internal or catalogue?
&lt;/h2&gt;

&lt;p&gt;The alert does not say which fields the file contains. No schema, no described sample, nothing to compare against. This is the filter that best separates a real leak from a rehash, and here it cannot even begin.&lt;/p&gt;

&lt;p&gt;Verdict: no data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Filter 3: is the data fresh?
&lt;/h2&gt;

&lt;p&gt;Also unknown. And there is a trap specific to this system: because millions of historical records were migrated into the SPGD, old data would not prove the claim false — the real system contains it. What would prove current access is recent records, and nobody has shown any.&lt;/p&gt;

&lt;p&gt;Verdict: no data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Filter 4: has anyone cross-checked it against previous leaks?
&lt;/h2&gt;

&lt;p&gt;Not that anyone has published. With one piece of arithmetic on top: 10,000 lines against more than four million records is &lt;strong&gt;0.25%&lt;/strong&gt; of the system. That could be a sample to prove access, it could be everything someone has, or it could be a slice of something else. All three explanations produce exactly the same link.&lt;/p&gt;

&lt;p&gt;Verdict: no data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Filter 5: who is telling you?
&lt;/h2&gt;

&lt;p&gt;An aggregator. One that, to its credit, labels the alert unconfirmed from its first line. The risk comes afterwards: every time someone forwards it, that label is the first thing to fall off. "Alleged leak, unconfirmed" becomes "the Police got hacked" within two forwards.&lt;/p&gt;

&lt;p&gt;And a detail worth writing down: the alias this post is attributed to &lt;strong&gt;differs by one character&lt;/strong&gt; from the one the press attributed to the Claro claim. It could be the same person, someone's transcription error, or an imitator riding the name of the moment. I do not know, and whoever tells you they do does not know either.&lt;/p&gt;

&lt;p&gt;Verdict: a source that is honest about its own uncertainty. The forwards will not be.&lt;/p&gt;

&lt;h2&gt;
  
  
  The scoreboard
&lt;/h2&gt;

&lt;p&gt;Five filters: one with partial evidence, three with no data, one that describes the messenger. &lt;strong&gt;That is not "false." It is "unknown."&lt;/strong&gt; And unknown is a complete answer — the only honest one today.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do if you filed a complaint
&lt;/h2&gt;

&lt;p&gt;The advice here is not the Claro advice. There is no second factor to move.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If "the Police" call you with details of your case, that no longer proves anything.&lt;/strong&gt; Knowing your complaint does not show the caller is an officer. If they ask for money, data, or for you to go somewhere: hang up, and verify yourself at your station or through official channels.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you reported an abuser and this worries you&lt;/strong&gt;, the Ministry of Women's Línea Mujer is &lt;code&gt;*212&lt;/code&gt;: free, confidential, 24 hours, dialled from any Altice, Claro or Viva mobile in the Dominican Republic. Do not wait for anyone to confirm anything before calling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And do not go looking to see whether you are in the file.&lt;/strong&gt; It is the natural reaction, and it is exactly the one bait relies on.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means for those of us who build systems
&lt;/h2&gt;

&lt;p&gt;The alert's technical recommendation is its most useful part, and it applies to everyone: audit the access logs to identify which user or IP recently ran mass queries or exported 10,000 records.&lt;/p&gt;

&lt;p&gt;The uncomfortable question is whether your system could answer it. Is it logged who exports? Does an alert fire when one account reads ten thousand rows in an afternoon? A system with more than 170 points of entry has more than 170 sets of credentials; the question is never whether one gets compromised, but how much it can read before anyone notices.&lt;/p&gt;

&lt;p&gt;That capability — being able to say within hours "yes, that was ours" or "no, it was not" — is the same one I asked for in the Claro post. Four days later it is the missing piece again.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sources:&lt;/strong&gt; the alert is from VECERT Analyzer, marked unconfirmed by the account itself · &lt;a href="https://www.policianacional.gob.do/policia-nacional-moderniza-certificaciones-vehiculares-y-denuncias-con-plataforma-digital/" rel="noopener noreferrer"&gt;National Police, on the SPGD&lt;/a&gt; · &lt;a href="https://denuncias.policia.gob.do/" rel="noopener noreferrer"&gt;Complaints portal&lt;/a&gt; · &lt;a href="https://mujer.gob.do/index.php/servicios/linea-mujer-212" rel="noopener noreferrer"&gt;Línea Mujer *212&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I write up the things I break and fix at &lt;a href="https://codewithgabo.com/allpost?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=the-next-leak-claim-took-four-days" rel="noopener noreferrer"&gt;codewithgabo.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>security</category>
      <category>privacy</category>
      <category>webdev</category>
      <category>cybersecurity</category>
    </item>
    <item>
      <title>Lo de Claro: qué se sabe, qué no, y qué hacer igual</title>
      <dc:creator>Gabriel Abreu</dc:creator>
      <pubDate>Wed, 16 Sep 2026 17:16:48 +0000</pubDate>
      <link>https://dev.to/gabbs279/lo-de-claro-que-se-sabe-que-no-y-que-hacer-igual-24p9</link>
      <guid>https://dev.to/gabbs279/lo-de-claro-que-se-sabe-que-no-y-que-hacer-igual-24p9</guid>
      <description>&lt;p&gt;El 13 de septiembre apareció en un foro la afirmación de que alguien había accedido a los sistemas de Claro en República Dominicana y sacado una base con &lt;strong&gt;2,889,256 registros de clientes&lt;/strong&gt;. La cifra se repitió rápido, amplificada desde X, y en cuestión de horas medio país la daba por hecha.&lt;/p&gt;

&lt;p&gt;Vale la pena separar dos cosas que se mezclaron enseguida: lo que se afirmó y lo que está comprobado. No son lo mismo, y la diferencia cambia qué deberías hacer tú.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué se afirmó
&lt;/h2&gt;

&lt;p&gt;Según la publicación, cada registro incluiría:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Número de identificación&lt;/li&gt;
&lt;li&gt;Número de teléfono&lt;/li&gt;
&lt;li&gt;Información de la suscripción&lt;/li&gt;
&lt;li&gt;Estado de la cuenta&lt;/li&gt;
&lt;li&gt;Categoría del plan&lt;/li&gt;
&lt;li&gt;Fecha de activación&lt;/li&gt;
&lt;li&gt;Ciclo de facturación&lt;/li&gt;
&lt;li&gt;Códigos internos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ICCID&lt;/strong&gt;, el identificador único de cada tarjeta SIM&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ese último campo es el que más dice. El ICCID no es un dato de mercadeo: identifica una SIM en concreto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué no está comprobado
&lt;/h2&gt;

&lt;p&gt;Prácticamente todo lo demás.&lt;/p&gt;

&lt;p&gt;La afirmación &lt;strong&gt;no se ha podido comprobar de forma independiente&lt;/strong&gt;. Las muestras difundidas no permiten establecer por sí solas el origen de los datos, ni demuestran que la información sea reciente, completa, ni que salga de los sistemas de la empresa.&lt;/p&gt;

&lt;p&gt;Claro Dominicana &lt;strong&gt;no ha confirmado públicamente&lt;/strong&gt; ningún incidente. Al momento de escribir esto tampoco aparecen investigaciones ni notificaciones anunciadas por autoridades dominicanas.&lt;/p&gt;

&lt;p&gt;Así que el estado real es: una alegación difundida en redes, no una filtración confirmada.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por qué eso no te deja tranquilo
&lt;/h2&gt;

&lt;p&gt;Aquí es donde casi todo el mundo saca la conclusión equivocada, en una dirección o en la otra.&lt;/p&gt;

&lt;p&gt;Unos leen "no está confirmado" y siguen igual. Otros leen la cifra y entran en pánico. Las dos reacciones tratan la incertidumbre como si fuera información.&lt;/p&gt;

&lt;p&gt;Míralo por el costo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Si la filtración es falsa&lt;/strong&gt; y tú moviste tu autenticación de dos pasos fuera del SMS, perdiste veinte minutos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Si es real&lt;/strong&gt; y esperaste la confirmación oficial, esperaste justo durante la ventana en que esos datos valen más.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No es simétrico. Y la confirmación, cuando llega, suele llegar tarde: primero hay que verificar, luego decidir qué se comunica, y eso toma días o semanas. Mientras tanto, lo que estuviera circulando ya circuló.&lt;/p&gt;

&lt;p&gt;La ausencia de confirmación no es confirmación de ausencia.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué haría alguien con esos datos, si fueran reales
&lt;/h2&gt;

&lt;p&gt;No hace falta imaginar escenarios de película. Con cédula, teléfono, plan y ciclo de facturación, dos ataques normales se vuelven mucho más fáciles.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;El primero es la llamada que sabe cosas de ti.&lt;/strong&gt; El esquema de siempre —"le llamamos de su compañía telefónica"— falla porque el que llama no sabe nada. Con esos campos sí sabe: tu nombre, tu cédula, qué plan tienes y cuándo te facturan. Toda la pregunta de seguridad que tu banco te hace por teléfono está en esa lista.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;El segundo es el cambio de SIM.&lt;/strong&gt; Si alguien convence a un punto de servicio de que es tú y se lleva tu número a otra SIM, hereda tus mensajes. Y ahí es donde duele: &lt;strong&gt;el SMS sigue siendo el segundo factor de casi todo en el país.&lt;/strong&gt; Tu banco, tu correo, tus redes. Quien controla tu número puede pedir el código de recuperación de todo lo demás.&lt;/p&gt;

&lt;p&gt;Por eso el dato del ICCID no es un detalle técnico aburrido. Es el que convierte una lista de clientes en una lista de objetivos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué hacer esta semana
&lt;/h2&gt;

&lt;p&gt;Ninguna de estas cosas depende de que la filtración se confirme.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Saca tu segundo factor del SMS.&lt;/strong&gt; Correo, banco, redes: donde se pueda, usa una app de autenticación. Es el cambio con más efecto por minuto invertido, y es el único que te protege si tu número deja de ser tuyo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pregunta en tu compañía qué hace falta para cambiar tu número de SIM.&lt;/strong&gt; Si la respuesta es "una llamada", eso es el problema. Pide que exija presencia física o una clave adicional, si lo ofrecen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ponle PIN a la SIM.&lt;/strong&gt; Es el menú de seguridad del teléfono, toma un minuto, y bloquea el caso simple de que te roben el equipo y saquen la tarjeta.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cambia tu regla mental sobre quién te llama.&lt;/strong&gt; Que alguien sepa tu cédula ya no prueba nada. Nunca fue una buena prueba; ahora ni siquiera es una mala. Si te llaman de tu banco, cuelga y llama tú al número de la tarjeta.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Y nunca leas un código en voz alta.&lt;/strong&gt; Ningún banco, ninguna telefónica y ninguna app te va a pedir por teléfono el código que te acaba de llegar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lo que nos toca a los que construimos software
&lt;/h2&gt;

&lt;p&gt;Si tú haces sistemas para clientes dominicanos, esto cambia dos supuestos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;El primero: la cédula y el teléfono no son secretos.&lt;/strong&gt; Nunca lo fueron del todo, pero cualquier sistema que verifique identidad preguntando la cédula está haciendo teatro. Si tu recuperación de cuenta se apoya en "dime tu número de documento", tu recuperación de cuenta es pública.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;El segundo: el OTP por SMS es un factor prestado.&lt;/strong&gt; No lo controlas tú, lo controla la operadora, y su seguridad es la de su punto de atención al cliente. Si tu app protege dinero o datos sensibles, ofrece al menos la opción de una app de autenticación.&lt;/p&gt;

&lt;p&gt;Y hay un tercero, más incómodo, que aplica aunque este caso resulte falso: &lt;strong&gt;tú también estás a un export de distancia.&lt;/strong&gt; Casi toda base de datos de clientes puede volcarse completa desde adentro. Las preguntas útiles no son de firewall:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;¿Cuántos campos guardas que nunca usas? Cada uno es superficie.&lt;/li&gt;
&lt;li&gt;¿Quién puede exportar la tabla de clientes completa, y queda registrado?&lt;/li&gt;
&lt;li&gt;Si mañana aparece un volcado con tu esquema, ¿podrías decir en horas si es tuyo y de cuándo?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esa última es la que separa una respuesta creíble de un silencio de dos semanas.&lt;/p&gt;

&lt;h2&gt;
  
  
  El marco legal, y su hueco
&lt;/h2&gt;

&lt;p&gt;En República Dominicana la referencia es la &lt;strong&gt;Ley 172-13&lt;/strong&gt;, del 13 de diciembre de 2013, sobre protección de datos de carácter personal. Lo que sí establece con claridad:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;El tratamiento de datos exige consentimiento previo, libre, inequívoco y específico del titular, salvo las excepciones que la propia ley contempla.&lt;/li&gt;
&lt;li&gt;Quien trata datos debe adoptar &lt;strong&gt;medidas técnicas y organizativas&lt;/strong&gt; para evitar accesos no autorizados o alteraciones.&lt;/li&gt;
&lt;li&gt;Tú tienes derecho a que rectifiquen, actualicen o supriman tus datos, y el responsable tiene un plazo máximo de &lt;strong&gt;diez días hábiles&lt;/strong&gt; desde tu reclamo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lo que no encontré en las fuentes que revisé es una obligación explícita de &lt;strong&gt;notificar una brecha&lt;/strong&gt; a los afectados. Si existe en algún reglamento posterior, no me topé con ella, y me parece relevante decirlo así en vez de afirmar lo contrario.&lt;/p&gt;

&lt;p&gt;Ese hueco explica bastante. Cuando no hay un reloj legal corriendo, "no comentamos" es una estrategia viable. En Europa no lo sería: el reglamento allá obliga a notificar en 72 horas. Aquí el incentivo apunta al otro lado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cómo funciona un cambio de SIM fraudulento
&lt;/h2&gt;

&lt;p&gt;Vale la pena entenderlo, porque la defensa se vuelve obvia cuando ves el orden de los pasos.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Quien ataca ya sabe quién eres.&lt;/strong&gt; Nombre, cédula, número, plan. Con eso no necesita adivinar nada.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Llama o se presenta como tú&lt;/strong&gt; y pide un reemplazo de SIM: que se le perdió el teléfono, que la tarjeta se dañó. Responde las preguntas de verificación porque las respuestas están en la lista.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tu teléfono se queda sin señal.&lt;/strong&gt; Esa es la única señal de alarma que recibes, y es fácil confundirla con un problema de red. Ese detalle es el que hace que el ataque funcione de noche.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ahora tus SMS llegan a otro equipo.&lt;/strong&gt; Entra a tu correo con "olvidé mi contraseña", recibe el código, y desde el correo cae todo lo demás.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Fíjate dónde está el punto débil: no es tu contraseña, ni tu teléfono, ni siquiera tus datos. Es el mostrador donde alguien decide si el que llama eres tú. Tu seguridad depende del entrenamiento de una persona que no conoces, que atiende a cien clientes al día.&lt;/p&gt;

&lt;p&gt;Por eso mover el segundo factor fuera del SMS es la única defensa que no depende de esa persona.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cómo leer la próxima afirmación de filtración
&lt;/h2&gt;

&lt;p&gt;Va a haber otra. Conviene tener criterios antes, no durante.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Hay muestra verificable?&lt;/strong&gt; No "capturas de pantalla": registros que alguien independiente pueda cruzar con datos reales conocidos. Una captura no prueba origen; un CSV con mil filas que cuadran, sí.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Los campos son internos o de catálogo?&lt;/strong&gt; Un teléfono y un nombre pueden salir de cualquier lado. Un ICCID, un código interno o un ciclo de facturación no aparecen en un formulario público. Los campos que solo existen dentro del sistema son la parte difícil de falsificar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Los datos son frescos?&lt;/strong&gt; La pregunta que más filtraciones tumba. Si en la muestra no hay una sola línea activada este año, probablemente estás viendo datos viejos, de otra brecha, revendidos con etiqueta nueva.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Alguien cruzó la muestra con filtraciones anteriores?&lt;/strong&gt; Reempaquetar volcados viejos y venderlos como nuevos es un negocio, no una excepción. Es la explicación más aburrida y por eso la más frecuente.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Y quién lo está contando?&lt;/strong&gt; Una cuenta que agrega filtraciones no es una fuente que las verifica. Amplificar y comprobar son dos oficios distintos.&lt;/p&gt;

&lt;p&gt;Con esos cinco filtros, la mayoría de los sustos de internet se resuelven solos en un día.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué debería publicar una empresa para cerrar el tema
&lt;/h2&gt;

&lt;p&gt;Aquí hay una asimetría que casi nadie nota: &lt;strong&gt;la empresa es la única que puede cerrar esto barato.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Quien afirma tener los datos no puede probar el origen sin exponerse. Quien los revisa desde fuera solo puede decir "parece plausible". Pero la empresa tiene el esquema de su propia base. Sabe si un campo llamado como aparece en la muestra existe en sus sistemas, sabe si ese formato de código interno es suyo, y sabe si las fechas de activación corresponden a su historia.&lt;/p&gt;

&lt;p&gt;Un comunicado útil tiene tres frases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Revisamos la muestra&lt;/strong&gt;, y estos campos corresponden o no corresponden a nuestro esquema.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Si corresponden&lt;/strong&gt;, este es el alcance y estas son las cuentas afectadas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Esto es lo que debes hacer tú&lt;/strong&gt;, con instrucciones concretas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Un comunicado inútil dice que la seguridad de los clientes es prioritaria.&lt;/p&gt;

&lt;p&gt;El silencio tiene un costo que no se ve en el momento: deja a todo el mundo gestionando el peor caso por su cuenta. Y deja vivo el rumor, que es más difícil de matar en dos semanas que en dos días.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cómo termina esto, probablemente
&lt;/h2&gt;

&lt;p&gt;Hay tres finales posibles. Que alguien verifique las muestras y resulten auténticas. Que se demuestre que son datos viejos, recombinados de filtraciones anteriores —pasa más de lo que uno cree—. O que no pase nada y la historia se apague en dos semanas sin que nadie sepa.&lt;/p&gt;

&lt;p&gt;El tercero es el más probable. Y es el peor, porque deja a todo el mundo con la misma duda y sin ninguna razón para cambiar nada.&lt;/p&gt;

&lt;p&gt;Por eso el consejo de arriba no depende del final. Mover tu segundo factor fuera del SMS te conviene igual si esto resultó ser humo, igual si resultó ser cierto, e igual la próxima vez que aparezca una lista con tu nombre.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fuentes:&lt;/strong&gt; &lt;a href="https://n.com.do/2026/09/13/usuario-asegura-haber-accedido-a-datos-de-casi-2-9-millones-de-clientes-de-claro-en-rd/" rel="noopener noreferrer"&gt;N Digital&lt;/a&gt; · &lt;a href="https://eyr.com.do/presunta-filtracion-datos-clientes-claro-dominicana/" rel="noopener noreferrer"&gt;EyR&lt;/a&gt; · &lt;a href="https://www.one.gob.do/media/u5ohmfyp/ley-172-13.pdf" rel="noopener noreferrer"&gt;Ley 172-13, texto oficial&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I write up the things I break and fix at &lt;a href="https://codewithgabo.com/allpost?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=lo-de-claro-que-se-sabe-y-que-no" rel="noopener noreferrer"&gt;codewithgabo.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>security</category>
      <category>privacy</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The Claro Claim: What Is Known, What Is Not, and What to Do Anyway</title>
      <dc:creator>Gabriel Abreu</dc:creator>
      <pubDate>Wed, 16 Sep 2026 17:16:12 +0000</pubDate>
      <link>https://dev.to/gabbs279/the-claro-claim-what-is-known-what-is-not-and-what-to-do-anyway-4gl6</link>
      <guid>https://dev.to/gabbs279/the-claro-claim-what-is-known-what-is-not-and-what-to-do-anyway-4gl6</guid>
      <description>&lt;p&gt;On September 13 a forum post claimed that someone had broken into Claro's systems in the Dominican Republic and taken a database of &lt;strong&gt;2,889,256 customer records&lt;/strong&gt;. The number travelled fast, amplified from X, and within hours half the country was treating it as fact.&lt;/p&gt;

&lt;p&gt;Two things got merged immediately that are worth pulling apart: what was claimed, and what has been verified. They are not the same, and the difference changes what you should do.&lt;/p&gt;

&lt;h2&gt;
  
  
  What was claimed
&lt;/h2&gt;

&lt;p&gt;According to the post, each record would include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;National identification number&lt;/li&gt;
&lt;li&gt;Phone number&lt;/li&gt;
&lt;li&gt;Subscription information&lt;/li&gt;
&lt;li&gt;Account status&lt;/li&gt;
&lt;li&gt;Plan category&lt;/li&gt;
&lt;li&gt;Activation date&lt;/li&gt;
&lt;li&gt;Billing cycle&lt;/li&gt;
&lt;li&gt;Internal codes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ICCID&lt;/strong&gt;, the unique identifier of each SIM card&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last field is the one that says the most. An ICCID is not a marketing attribute: it identifies one specific SIM.&lt;/p&gt;

&lt;h2&gt;
  
  
  What has not been verified
&lt;/h2&gt;

&lt;p&gt;Nearly everything else.&lt;/p&gt;

&lt;p&gt;The claim &lt;strong&gt;could not be verified independently&lt;/strong&gt;. The circulated samples do not establish the origin of the data on their own, and they do not show the information is recent, complete, or taken from the company's systems.&lt;/p&gt;

&lt;p&gt;Claro Dominicana &lt;strong&gt;has not publicly confirmed&lt;/strong&gt; any incident. At the time of writing, no Dominican authority has announced an investigation or a notification either.&lt;/p&gt;

&lt;p&gt;So the honest status is: an allegation circulating on social media, not a confirmed breach.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why that does not let you relax
&lt;/h2&gt;

&lt;p&gt;This is where most people draw the wrong conclusion, in one direction or the other.&lt;/p&gt;

&lt;p&gt;Some read "unconfirmed" and carry on. Others read the number and panic. Both reactions treat uncertainty as if it were information.&lt;/p&gt;

&lt;p&gt;Look at the cost instead:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;If the leak is fake&lt;/strong&gt; and you moved your two-factor authentication off SMS, you lost twenty minutes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If it is real&lt;/strong&gt; and you waited for official confirmation, you waited during exactly the window when that data is worth the most.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is not symmetric. And confirmation, when it arrives, usually arrives late: first someone has to verify, then decide what to say, and that takes days or weeks. Whatever was circulating has already circulated.&lt;/p&gt;

&lt;p&gt;Absence of confirmation is not confirmation of absence.&lt;/p&gt;

&lt;h2&gt;
  
  
  What someone could do with that data, if it were real
&lt;/h2&gt;

&lt;p&gt;No need to imagine film plots. With an ID number, a phone, a plan and a billing cycle, two ordinary attacks get much easier.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The first is the call that knows things about you.&lt;/strong&gt; The old script — "we're calling from your phone company" — fails because the caller knows nothing. With those fields they do: your name, your ID, which plan you have, when you get billed. Every security question your bank asks over the phone is on that list.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The second is the SIM swap.&lt;/strong&gt; If someone convinces a service desk that they are you and moves your number to another SIM, they inherit your messages. And that is where it hurts: &lt;strong&gt;SMS is still the second factor for almost everything here.&lt;/strong&gt; Your bank, your email, your accounts. Whoever controls your number can request the recovery code for everything else.&lt;/p&gt;

&lt;p&gt;That is why the ICCID is not a boring technical detail. It is what turns a customer list into a target list.&lt;/p&gt;

&lt;h2&gt;
  
  
  How a fraudulent SIM swap actually works
&lt;/h2&gt;

&lt;p&gt;Worth understanding, because the defence becomes obvious once you see the order of the steps.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The attacker already knows who you are.&lt;/strong&gt; Name, ID, number, plan. Nothing to guess.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;They present as you&lt;/strong&gt; and ask for a replacement SIM: lost phone, damaged card. They answer the verification questions because the answers are on the list.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your phone loses signal.&lt;/strong&gt; That is the only alarm you get, and it is easy to mistake for a network problem. That detail is why the attack works at night.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your texts now arrive on another device.&lt;/strong&gt; They open your email with "forgot my password", receive the code, and from the email everything else falls.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Notice where the weak point sits: not your password, not your phone, not even your data. It is the counter where a person decides whether the caller is you. Your security depends on the training of someone you have never met, serving a hundred customers a day.&lt;/p&gt;

&lt;p&gt;That is why moving your second factor off SMS is the only defence that does not depend on that person.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do this week
&lt;/h2&gt;

&lt;p&gt;None of this depends on the leak being confirmed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Move your second factor off SMS.&lt;/strong&gt; Email, bank, social accounts: wherever it is offered, use an authenticator app. It is the highest-value change per minute spent, and the only one that protects you if your number stops being yours.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ask your carrier what it takes to move your number to a new SIM.&lt;/strong&gt; If the answer is "a phone call", that is the problem. Ask whether they offer in-person verification or an extra passphrase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Put a PIN on the SIM.&lt;/strong&gt; It is in your phone's security menu, takes a minute, and blocks the simple case where someone steals the handset and pulls the card.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Change your mental rule about who calls you.&lt;/strong&gt; Someone knowing your ID number proves nothing now. It was never good proof; today it is not even weak proof. If your bank calls, hang up and call the number on the card.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And never read a code out loud.&lt;/strong&gt; No bank, no carrier and no app will ask you over the phone for the code that just arrived.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means for those of us who build software
&lt;/h2&gt;

&lt;p&gt;If you build systems for Dominican customers, two assumptions changed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First: ID numbers and phone numbers are not secrets.&lt;/strong&gt; They never fully were, but any system verifying identity by asking for a national ID is performing theatre. If your account recovery rests on "tell me your document number", your account recovery is public.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Second: SMS OTP is a borrowed factor.&lt;/strong&gt; You do not control it — the carrier does, and its security is the security of their customer service desk. If your app protects money or sensitive data, at least offer an authenticator app.&lt;/p&gt;

&lt;p&gt;And a third, less comfortable one that applies even if this case turns out to be false: &lt;strong&gt;you are one export away too.&lt;/strong&gt; Almost every customer database can be dumped whole from the inside. The useful questions are not about firewalls:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How many fields do you store that you never use? Each one is surface.&lt;/li&gt;
&lt;li&gt;Who can export the full customer table, and is it logged?&lt;/li&gt;
&lt;li&gt;If a dump with your schema appeared tomorrow, could you say within hours whether it is yours and how old it is?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last one is what separates a credible response from two weeks of silence.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to read the next leak claim
&lt;/h2&gt;

&lt;p&gt;There will be another one. Better to have criteria beforehand than during.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is there a verifiable sample?&lt;/strong&gt; Not screenshots: records an independent party can cross-check against known real data. A screenshot proves nothing about origin; a thousand rows that line up does.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Are the fields internal or catalogue?&lt;/strong&gt; A name and a phone number can come from anywhere. An ICCID, an internal code or a billing cycle do not appear on a public form. The fields that exist only inside the system are the hard part to fake.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is the data fresh?&lt;/strong&gt; The question that kills most claims. If not one line in the sample was activated this year, you are probably looking at old data from another breach, resold under a new label.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Has anyone cross-checked it against previous leaks?&lt;/strong&gt; Repackaging old dumps and selling them as new is a business, not an exception. It is the most boring explanation and therefore the most common one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And who is telling you?&lt;/strong&gt; An account that aggregates leaks is not a source that verifies them. Amplifying and checking are two different jobs.&lt;/p&gt;

&lt;p&gt;With those five filters, most internet scares resolve themselves within a day.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a company should publish to end it
&lt;/h2&gt;

&lt;p&gt;There is an asymmetry almost nobody notices: &lt;strong&gt;the company is the only party that can close this cheaply.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Whoever claims to hold the data cannot prove its origin without exposing themselves. Anyone reviewing from outside can only say "looks plausible". But the company has its own schema. It knows whether a field named the way the sample names it exists in its systems, whether that internal code format is theirs, and whether those activation dates match its own history.&lt;/p&gt;

&lt;p&gt;A useful statement is three sentences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;We reviewed the sample&lt;/strong&gt;, and these fields do or do not match our schema.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If they match&lt;/strong&gt;, this is the scope and these are the affected accounts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Here is what you should do&lt;/strong&gt;, with concrete instructions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A useless statement says customer security is a priority.&lt;/p&gt;

&lt;p&gt;Silence carries a cost that is invisible at the time: it leaves everyone managing the worst case alone. And it keeps the rumour alive, which is harder to kill in two weeks than in two days.&lt;/p&gt;

&lt;h2&gt;
  
  
  The legal frame, and its gap
&lt;/h2&gt;

&lt;p&gt;In the Dominican Republic the reference is &lt;strong&gt;Ley 172-13&lt;/strong&gt;, of December 13, 2013, on the protection of personal data. What it clearly establishes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Processing personal data requires the subject's prior, free, unambiguous and specific consent, save the exceptions the law itself sets out.&lt;/li&gt;
&lt;li&gt;Whoever processes data must adopt &lt;strong&gt;technical and organisational measures&lt;/strong&gt; to prevent unauthorised access or alteration.&lt;/li&gt;
&lt;li&gt;You have the right to have your data rectified, updated or deleted, and the controller has a maximum of &lt;strong&gt;ten business days&lt;/strong&gt; from your claim.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What I did not find in the sources I checked is an explicit obligation to &lt;strong&gt;notify a breach&lt;/strong&gt; to those affected. If a later regulation creates one, I did not come across it, and that seems worth saying plainly instead of asserting the opposite.&lt;/p&gt;

&lt;p&gt;That gap explains a lot. When no legal clock is running, "no comment" is a viable strategy. In Europe it would not be: the regulation there requires notification within 72 hours. Here the incentive points the other way.&lt;/p&gt;

&lt;h2&gt;
  
  
  How this probably ends
&lt;/h2&gt;

&lt;p&gt;There are three possible endings. Someone verifies the samples and they turn out to be authentic. Someone shows they are old data, recombined from earlier leaks — which happens more than people think. Or nothing happens and the story fades in two weeks without anyone knowing.&lt;/p&gt;

&lt;p&gt;The third is the most likely. And it is the worst, because it leaves everyone with the same doubt and no reason to change anything.&lt;/p&gt;

&lt;p&gt;That is why the advice above does not depend on the ending. Moving your second factor off SMS is worth it if this turns out to be smoke, worth it if it turns out to be true, and worth it the next time a list with your name on it shows up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sources:&lt;/strong&gt; &lt;a href="https://n.com.do/2026/09/13/usuario-asegura-haber-accedido-a-datos-de-casi-2-9-millones-de-clientes-de-claro-en-rd/" rel="noopener noreferrer"&gt;N Digital&lt;/a&gt; · &lt;a href="https://eyr.com.do/presunta-filtracion-datos-clientes-claro-dominicana/" rel="noopener noreferrer"&gt;EyR&lt;/a&gt; · &lt;a href="https://www.one.gob.do/media/u5ohmfyp/ley-172-13.pdf" rel="noopener noreferrer"&gt;Ley 172-13, official text&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I write up the things I break and fix at &lt;a href="https://codewithgabo.com/allpost?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=the-claro-claim-what-is-known-and-what-is-not" rel="noopener noreferrer"&gt;codewithgabo.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>security</category>
      <category>privacy</category>
      <category>webdev</category>
    </item>
    <item>
      <title>React 19.3, el compilador y un CVSS 10: lo que cambió mientras no mirabas</title>
      <dc:creator>Gabriel Abreu</dc:creator>
      <pubDate>Wed, 16 Sep 2026 00:12:20 +0000</pubDate>
      <link>https://dev.to/gabbs279/react-193-el-compilador-y-un-cvss-10-lo-que-cambio-mientras-no-mirabas-c2d</link>
      <guid>https://dev.to/gabbs279/react-193-el-compilador-y-un-cvss-10-lo-que-cambio-mientras-no-mirabas-c2d</guid>
      <description>&lt;p&gt;Esta semana saqué Create React App de un proyecto y dejé escrito el plan para sacarlo de otro. Los dos eran de 2022 y 2023, y los dos seguían funcionando. Eso es lo engañoso: seguir funcionando y seguir siendo la forma correcta de hacerlo son cosas distintas, y entre una y otra pasaron cuatro cambios grandes en React que no se enteran solos.&lt;/p&gt;

&lt;p&gt;Ninguno es un rumor. Los cuatro están publicados en el blog oficial, con fecha.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. El compilador ya borra tu &lt;code&gt;useMemo&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;React Compiler llegó a la versión 1.0 el 7 de octubre de 2025.&lt;/strong&gt; No es beta, no es experimento: memoriza automáticamente componentes y hooks, funciona en React y en React Native, y se instala con Babel, Vite o Rsbuild.&lt;/p&gt;

&lt;p&gt;Lo que eso significa en la práctica es que la mayoría de tus &lt;code&gt;useMemo&lt;/code&gt; y &lt;code&gt;useCallback&lt;/code&gt; dejaron de ser trabajo tuyo. Los escribías para evitar renders; el compilador hace esa optimización en tiempo de compilación, sin reescribir nada.&lt;/p&gt;

&lt;p&gt;Hay un detalle de instalación que se come a mucha gente: &lt;strong&gt;si tenías &lt;code&gt;eslint-plugin-react-compiler&lt;/code&gt;, ya no va.&lt;/strong&gt; Se elimina y se usa &lt;code&gt;eslint-plugin-react-hooks@latest&lt;/code&gt;, porque las reglas del compilador ahora viajan dentro de sus presets &lt;code&gt;recommended&lt;/code&gt; y &lt;code&gt;recommended-latest&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;El compilador se apoya en las Reglas de React. Si tu componente las rompe, el compilador lo detecta y se salta ese componente en lugar de optimizarlo mal. Por eso las advertencias del linter dejaron de ser cosmética: ahora determinan si tu código se optimiza o no.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Si sirves Server Components, ahora tienes calendario de parches
&lt;/h2&gt;

&lt;p&gt;Este es el cambio que menos se comenta y más te puede costar.&lt;/p&gt;

&lt;p&gt;El &lt;strong&gt;3 de diciembre de 2025&lt;/strong&gt;, React publicó una vulnerabilidad crítica en React Server Components: &lt;strong&gt;CVE-2025-55182, con CVSS 10.0&lt;/strong&gt;, la puntuación máxima. Un atacante sin autenticar podía mandar una petición HTTP a cualquier endpoint de Server Function que, al deserializarse, lograba &lt;strong&gt;ejecución remota de código en el servidor&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Afectaba a &lt;code&gt;react-server-dom-webpack&lt;/code&gt;, &lt;code&gt;react-server-dom-parcel&lt;/code&gt; y &lt;code&gt;react-server-dom-turbopack&lt;/code&gt; en las versiones 19.0, 19.1.0, 19.1.1 y 19.2.0. Se arregló en &lt;strong&gt;19.0.1, 19.1.2 y 19.2.1&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Y la lista de frameworks afectados es la lista de lo que la gente usa: &lt;code&gt;next&lt;/code&gt;, &lt;code&gt;react-router&lt;/code&gt;, &lt;code&gt;waku&lt;/code&gt;, &lt;code&gt;@parcel/rsc&lt;/code&gt;, &lt;code&gt;@vitejs/plugin-rsc&lt;/code&gt; y &lt;code&gt;rwsdk&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ocho días después llegó la segunda tanda.&lt;/strong&gt; El 11 de diciembre se publicaron dos más:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Denegación de servicio&lt;/strong&gt; (CVE-2025-55184, CVE-2025-67779 y CVE-2026-23864, CVSS 7.5): peticiones maliciosas a endpoints de Server Function provocaban bucles infinitos que cuelgan el proceso, se comen el CPU y terminan en caídas o en falta de memoria.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exposición de código fuente&lt;/strong&gt; (CVE-2025-55183, CVSS 5.3): una petición podía devolver el código de tus Server Functions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;El detalle de esa última merece leerse con cuidado, porque decide si te afecta:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;serverFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SECRET KEY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// expuesto&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Hello, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!`&lt;/span&gt; &lt;span class="c1"&gt;// expuesto&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Solo se exponen los secretos &lt;strong&gt;escritos a mano en el código&lt;/strong&gt;. Los que vienen de &lt;code&gt;process.env&lt;/code&gt; no. O sea: si alguna vez pegaste una llave directo en un archivo con &lt;code&gt;'use server'&lt;/code&gt; para probar, ese es el archivo.&lt;/p&gt;

&lt;p&gt;Se arregló en &lt;strong&gt;19.0.4, 19.1.5 y 19.2.4&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;La conclusión operativa es sencilla y no es sobre React: si tu aplicación sirve Server Components, dejó de ser una dependencia que se actualiza cuando hay tiempo. Y si no usas RSC ni servidor, ninguna de estas te toca.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. React 19.3 trajo cosas que antes se resolvían fuera de React
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Salió el 9 de septiembre de 2026&lt;/strong&gt;, hace días.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;&amp;lt;ViewTransition&amp;gt;&lt;/code&gt;&lt;/strong&gt; te deja animar elementos cuando entran, salen, se mueven o cambian de tamaño, usando la View Transition API del navegador:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ViewTransition&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isShowing&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ViewTransition&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ViewTransition&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;React decide qué animación correr según cómo cambió el árbol: entrada, salida, actualización o compartida. Y si necesitas que la misma actualización de estado se anime distinto según &lt;strong&gt;por qué&lt;/strong&gt; ocurrió, &lt;code&gt;addTransitionType&lt;/code&gt; marca la causa:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;nextSlide&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;startTransition&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;addTransitionType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setCurrentSlide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ViewTransition&lt;/span&gt;
  &lt;span class="nx"&gt;enter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;from-right&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;previous&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;from-left&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}}&lt;/span&gt;
  &lt;span class="nx"&gt;exit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;to-left&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;previous&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;to-right&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}}&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Page&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ViewTransition&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Los refs en &lt;code&gt;Fragment&lt;/code&gt;&lt;/strong&gt; resuelven el problema de querer tocar el DOM de un grupo de elementos sin envolverlo en un &lt;code&gt;div&lt;/code&gt; que no necesitabas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Fragment&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;fragmentRef&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Heading&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Heading&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;))}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Fragment&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El &lt;code&gt;FragmentInstance&lt;/code&gt; trae un conjunto acotado de métodos: &lt;code&gt;addEventListener&lt;/code&gt;, &lt;code&gt;removeEventListener&lt;/code&gt;, &lt;code&gt;dispatchEvent&lt;/code&gt;, &lt;code&gt;focus&lt;/code&gt;, &lt;code&gt;focusLast&lt;/code&gt;, &lt;code&gt;blur&lt;/code&gt;, &lt;code&gt;observeUsing&lt;/code&gt;, &lt;code&gt;unobserveUsing&lt;/code&gt;, &lt;code&gt;getClientRects&lt;/code&gt;, &lt;code&gt;getRootNode&lt;/code&gt;, &lt;code&gt;compareDocumentPosition&lt;/code&gt; y &lt;code&gt;scrollIntoView&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ese &lt;code&gt;observeUsing&lt;/code&gt; es el que a mí me importa: conectar un &lt;code&gt;IntersectionObserver&lt;/code&gt; a una lista sin fabricar un contenedor solo para tener dónde agarrarse.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;browser()&lt;/code&gt;&lt;/strong&gt; le dice a un componente que no se renderice en el servidor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;use&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Durante el renderizado en servidor se muestra el &lt;code&gt;fallback&lt;/code&gt; del &lt;code&gt;Suspense&lt;/code&gt; más cercano. Cuando el componente hidrata en el cliente, &lt;code&gt;use(browser())&lt;/code&gt; ya no suspende y todo sigue normal. Es la versión oficial del truco del &lt;code&gt;useEffect&lt;/code&gt; con &lt;code&gt;isClient&lt;/code&gt; que todos hemos escrito.&lt;/p&gt;

&lt;p&gt;También llegó &lt;strong&gt;integración con Trusted Types&lt;/strong&gt;, que ayuda contra XSS basado en DOM: React ahora pasa esos valores sin convertirlos a texto, para que el navegador pueda validarlos.&lt;/p&gt;

&lt;p&gt;Y una que no se ve pero se siente: &lt;strong&gt;las transiciones ahora se renderizan de forma independiente&lt;/strong&gt; en vez de enredarse en un solo render. Una transición lenta ya no retrasa a las otras.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. React ya no depende solo de Meta
&lt;/h2&gt;

&lt;p&gt;En octubre de 2025 se anunció la &lt;strong&gt;React Foundation&lt;/strong&gt;, y el 24 de febrero de 2026 se publicó su nueva casa: la &lt;strong&gt;Linux Foundation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Ocho miembros fundadores platino: Amazon, Callstack, Expo, Huawei, Meta, Microsoft, Software Mansion y Vercel. Una junta directiva con representantes de cada uno y Seth Webster como director ejecutivo.&lt;/p&gt;

&lt;p&gt;Con una aclaración que conviene leer completa: &lt;strong&gt;la gobernanza técnica de React es independiente de la junta.&lt;/strong&gt; La dirección técnica la siguen marcando quienes contribuyen y mantienen React, no los miembros de la fundación.&lt;/p&gt;

&lt;p&gt;Para el que solo escribe componentes, esto no cambia nada mañana. Cambia el riesgo a cinco años, que es el que uno realmente asume cuando escoge un framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué hacer con todo esto
&lt;/h2&gt;

&lt;p&gt;Si tuviera que ordenarlo por urgencia:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Si sirves Server Components, revisa tu versión hoy.&lt;/strong&gt; Un CVSS 10.0 no se negocia.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Si escribes &lt;code&gt;useMemo&lt;/code&gt; por reflejo, prueba el compilador.&lt;/strong&gt; Y si tenías el plugin viejo de ESLint, quítalo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Si tienes un proyecto en Create React App&lt;/strong&gt;, React dejó de recomendarlo el 14 de febrero de 2025. Migrar toma menos de lo que parece.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lo de 19.3 puede esperar&lt;/strong&gt;, pero léelo: hay cosas ahí que estás resolviendo a mano ahora mismo.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Fuentes:&lt;/strong&gt; &lt;a href="https://react.dev/blog/2026/09/09/react-19-3" rel="noopener noreferrer"&gt;React 19.3&lt;/a&gt; · &lt;a href="https://react.dev/blog/2025/10/07/react-compiler-1" rel="noopener noreferrer"&gt;React Compiler v1.0&lt;/a&gt; · &lt;a href="https://react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-components" rel="noopener noreferrer"&gt;Vulnerabilidad crítica en RSC&lt;/a&gt; · &lt;a href="https://react.dev/blog/2025/12/11/denial-of-service-and-source-code-exposure-in-react-server-components" rel="noopener noreferrer"&gt;DoS y exposición de código en RSC&lt;/a&gt; · &lt;a href="https://react.dev/blog/2026/02/24/the-react-foundation" rel="noopener noreferrer"&gt;The React Foundation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I write up the things I break and fix at &lt;a href="https://codewithgabo.com/allpost?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=react-19-3-el-compilador-y-un-cvss-10" rel="noopener noreferrer"&gt;codewithgabo.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>security</category>
    </item>
    <item>
      <title>React 19.3, the Compiler, and a CVSS 10: What Changed While You Weren't Looking</title>
      <dc:creator>Gabriel Abreu</dc:creator>
      <pubDate>Wed, 16 Sep 2026 00:11:44 +0000</pubDate>
      <link>https://dev.to/gabbs279/react-193-the-compiler-and-a-cvss-10-what-changed-while-you-werent-looking-1h35</link>
      <guid>https://dev.to/gabbs279/react-193-the-compiler-and-a-cvss-10-what-changed-while-you-werent-looking-1h35</guid>
      <description>&lt;p&gt;This week I pulled Create React App out of one project and wrote the plan to pull it out of another. Both were from 2022 and 2023, and both still worked. That is the deceptive part: still working and still being the right way to do it are different things, and between the two, four large changes happened in React that do not announce themselves.&lt;/p&gt;

&lt;p&gt;None of this is rumour. All four are on the official blog, with dates.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The compiler already deletes your &lt;code&gt;useMemo&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;React Compiler reached 1.0 on October 7, 2025.&lt;/strong&gt; Not beta, not an experiment: it automatically memoizes components and hooks, works in React and React Native, and installs through Babel, Vite or Rsbuild.&lt;/p&gt;

&lt;p&gt;What that means in practice is that most of your &lt;code&gt;useMemo&lt;/code&gt; and &lt;code&gt;useCallback&lt;/code&gt; stopped being your job. You wrote them to avoid re-renders; the compiler does that optimization at build time, without rewriting anything.&lt;/p&gt;

&lt;p&gt;There is one installation detail that catches people: &lt;strong&gt;if you had &lt;code&gt;eslint-plugin-react-compiler&lt;/code&gt;, it is gone.&lt;/strong&gt; You remove it and use &lt;code&gt;eslint-plugin-react-hooks@latest&lt;/code&gt;, because the compiler's lint rules now ship inside its &lt;code&gt;recommended&lt;/code&gt; and &lt;code&gt;recommended-latest&lt;/code&gt; presets.&lt;/p&gt;

&lt;p&gt;The compiler leans on the Rules of React. If a component breaks them, the compiler detects it and skips that component rather than optimizing it wrongly. Which means linter warnings stopped being cosmetic: they now decide whether your code gets optimized at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. If you serve Server Components, you now have a patch calendar
&lt;/h2&gt;

&lt;p&gt;This is the change that gets discussed least and can cost you most.&lt;/p&gt;

&lt;p&gt;On &lt;strong&gt;December 3, 2025&lt;/strong&gt;, React published a critical vulnerability in React Server Components: &lt;strong&gt;CVE-2025-55182, CVSS 10.0&lt;/strong&gt;, the maximum score. An unauthenticated attacker could craft an HTTP request to any Server Function endpoint that, when deserialized by React, achieved &lt;strong&gt;remote code execution on the server&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It affected &lt;code&gt;react-server-dom-webpack&lt;/code&gt;, &lt;code&gt;react-server-dom-parcel&lt;/code&gt; and &lt;code&gt;react-server-dom-turbopack&lt;/code&gt; in versions 19.0, 19.1.0, 19.1.1 and 19.2.0. Fixed in &lt;strong&gt;19.0.1, 19.1.2 and 19.2.1&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And the list of affected frameworks is the list of what people actually use: &lt;code&gt;next&lt;/code&gt;, &lt;code&gt;react-router&lt;/code&gt;, &lt;code&gt;waku&lt;/code&gt;, &lt;code&gt;@parcel/rsc&lt;/code&gt;, &lt;code&gt;@vitejs/plugin-rsc&lt;/code&gt; and &lt;code&gt;rwsdk&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Eight days later came the second batch.&lt;/strong&gt; On December 11 two more were published:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Denial of service&lt;/strong&gt; (CVE-2025-55184, CVE-2025-67779 and CVE-2026-23864, CVSS 7.5): malicious requests to Server Function endpoints caused infinite loops that hang the process, eat CPU, and end in crashes or out-of-memory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Source code exposure&lt;/strong&gt; (CVE-2025-55183, CVSS 5.3): a request could return the source of your Server Functions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The detail in that last one is worth reading carefully, because it decides whether it touches you:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;serverFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SECRET KEY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// exposed&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Hello, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!`&lt;/span&gt; &lt;span class="c1"&gt;// exposed&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only secrets &lt;strong&gt;hardcoded in the source&lt;/strong&gt; are exposed. Ones coming from &lt;code&gt;process.env&lt;/code&gt; are not. So: if you ever pasted a key straight into a file with &lt;code&gt;'use server'&lt;/code&gt; to test something, that is the file.&lt;/p&gt;

&lt;p&gt;Fixed in &lt;strong&gt;19.0.4, 19.1.5 and 19.2.4&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The operational conclusion is simple and it isn't about React: if your app serves Server Components, it stopped being a dependency you update when there's time. And if you use neither RSC nor a server, none of these reach you.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. React 19.3 shipped things that used to be solved outside React
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;It came out on September 9, 2026&lt;/strong&gt;, days ago.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;&amp;lt;ViewTransition&amp;gt;&lt;/code&gt;&lt;/strong&gt; animates elements as they enter, exit, move or resize, using the browser's View Transition API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ViewTransition&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isShowing&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ViewTransition&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ViewTransition&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;React picks which animation to run based on how the tree changed: enter, exit, update or share. And when the same state update should animate differently depending on &lt;strong&gt;why&lt;/strong&gt; it happened, &lt;code&gt;addTransitionType&lt;/code&gt; marks the cause:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;nextSlide&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;startTransition&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;addTransitionType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setCurrentSlide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ViewTransition&lt;/span&gt;
  &lt;span class="nx"&gt;enter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;from-right&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;previous&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;from-left&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}}&lt;/span&gt;
  &lt;span class="nx"&gt;exit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;to-left&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;previous&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;to-right&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}}&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Page&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ViewTransition&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fragment refs&lt;/strong&gt; solve wanting to touch the DOM of a group of elements without wrapping it in a &lt;code&gt;div&lt;/code&gt; you never needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Fragment&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;fragmentRef&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Heading&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Heading&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;))}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Fragment&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;FragmentInstance&lt;/code&gt; carries a deliberately small set of methods: &lt;code&gt;addEventListener&lt;/code&gt;, &lt;code&gt;removeEventListener&lt;/code&gt;, &lt;code&gt;dispatchEvent&lt;/code&gt;, &lt;code&gt;focus&lt;/code&gt;, &lt;code&gt;focusLast&lt;/code&gt;, &lt;code&gt;blur&lt;/code&gt;, &lt;code&gt;observeUsing&lt;/code&gt;, &lt;code&gt;unobserveUsing&lt;/code&gt;, &lt;code&gt;getClientRects&lt;/code&gt;, &lt;code&gt;getRootNode&lt;/code&gt;, &lt;code&gt;compareDocumentPosition&lt;/code&gt; and &lt;code&gt;scrollIntoView&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;observeUsing&lt;/code&gt; is the one I care about: attaching an &lt;code&gt;IntersectionObserver&lt;/code&gt; to a list without manufacturing a container just to have something to hold.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;browser()&lt;/code&gt;&lt;/strong&gt; tells a component not to render on the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;use&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During server rendering the nearest &lt;code&gt;Suspense&lt;/code&gt; fallback shows. Once the component hydrates on the client, &lt;code&gt;use(browser())&lt;/code&gt; no longer suspends and rendering continues normally. It is the official version of the &lt;code&gt;useEffect&lt;/code&gt; plus &lt;code&gt;isClient&lt;/code&gt; trick everyone has written.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trusted Types integration&lt;/strong&gt; also landed, which helps against DOM-based XSS: React now passes those values through without coercing them to strings, so the browser can validate them.&lt;/p&gt;

&lt;p&gt;And one you don't see but feel: &lt;strong&gt;transitions now render independently&lt;/strong&gt; instead of being entangled into a single render. A slow transition no longer holds up unrelated ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. React no longer depends on Meta alone
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;React Foundation&lt;/strong&gt; was announced in October 2025, and on &lt;strong&gt;February 24, 2026&lt;/strong&gt; its new home was published: the &lt;strong&gt;Linux Foundation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Eight platinum founding members: Amazon, Callstack, Expo, Huawei, Meta, Microsoft, Software Mansion and Vercel. A board with a representative from each, and Seth Webster as executive director.&lt;/p&gt;

&lt;p&gt;With a clarification worth reading in full: &lt;strong&gt;React's technical governance is independent from that board.&lt;/strong&gt; Technical direction is still set by the people who contribute to and maintain React, not by the foundation's members.&lt;/p&gt;

&lt;p&gt;If you only write components, this changes nothing tomorrow. It changes the five-year risk, which is the one you actually take on when you pick a framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do with all of this
&lt;/h2&gt;

&lt;p&gt;If I had to order it by urgency:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;If you serve Server Components, check your version today.&lt;/strong&gt; A CVSS 10.0 is not a negotiation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If you write &lt;code&gt;useMemo&lt;/code&gt; by reflex, try the compiler.&lt;/strong&gt; And if you had the old ESLint plugin, remove it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If you have a project on Create React App&lt;/strong&gt;, React stopped recommending it on February 14, 2025. Migrating takes less than it looks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;19.3 can wait&lt;/strong&gt;, but read it: there are things in there you are solving by hand right now.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Sources:&lt;/strong&gt; &lt;a href="https://react.dev/blog/2026/09/09/react-19-3" rel="noopener noreferrer"&gt;React 19.3&lt;/a&gt; · &lt;a href="https://react.dev/blog/2025/10/07/react-compiler-1" rel="noopener noreferrer"&gt;React Compiler v1.0&lt;/a&gt; · &lt;a href="https://react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-components" rel="noopener noreferrer"&gt;Critical vulnerability in RSC&lt;/a&gt; · &lt;a href="https://react.dev/blog/2025/12/11/denial-of-service-and-source-code-exposure-in-react-server-components" rel="noopener noreferrer"&gt;DoS and source code exposure in RSC&lt;/a&gt; · &lt;a href="https://react.dev/blog/2026/02/24/the-react-foundation" rel="noopener noreferrer"&gt;The React Foundation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I write up the things I break and fix at &lt;a href="https://codewithgabo.com/allpost?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=react-19-3-the-compiler-and-a-cvss-10" rel="noopener noreferrer"&gt;codewithgabo.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>security</category>
    </item>
  </channel>
</rss>
