<?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: Jesus moo</title>
    <description>The latest articles on DEV Community by Jesus moo (@_jesmoo).</description>
    <link>https://dev.to/_jesmoo</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3886157%2F05485d05-1a04-44b0-9a6b-318c56fa7bfc.jpg</url>
      <title>DEV Community: Jesus moo</title>
      <link>https://dev.to/_jesmoo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/_jesmoo"/>
    <language>en</language>
    <item>
      <title>The customer paid to build the product herself</title>
      <dc:creator>Jesus moo</dc:creator>
      <pubDate>Sun, 17 May 2026 20:26:25 +0000</pubDate>
      <link>https://dev.to/_jesmoo/the-customer-paid-to-build-the-product-herself-f5a</link>
      <guid>https://dev.to/_jesmoo/the-customer-paid-to-build-the-product-herself-f5a</guid>
      <description>&lt;p&gt;Marta opened a laptop on her clinic's front desk and turned the screen toward me. The interface wasn't QVET. It wasn't Panther. It wasn't anything I had researched the week before. She had paid a developer to build it from scratch, because nothing on the market did what she needed.&lt;/p&gt;

&lt;p&gt;I'm a software engineer based in Guadalajara, and for the last two sprints I've been trying to validate a B2B SaaS for independent veterinary clinics, one to three doctors, sometimes with a groomer in the back, sometimes with a small hospital, often all three under one roof. I started with cold DMs on Instagram and WhatsApp. Seven sent, zero answered. So I switched to physical visits: walk in, ask to speak to the owner or lead vet for ten minutes, no pitch because I have nothing to pitch. In two weeks I visited 16 clinics, had 8 to 10 real conversations, and 3 vets agreed to follow-up calls. My starting hypothesis was that small clinics handle appointment reminders manually and that a meaningful fraction of returning patients miss their scheduled date. That turned out to be partially right, Marta's clinic runs at a 20% cancellation rate, the only hard no-show number i have, but it was wrong about which problem the software should solve first.&lt;/p&gt;

&lt;p&gt;Marta runs the clinic with one doctor (herself), a receptionist, and a manager who handles operations. She tried QVET, the Spanish veterinary PIMS that has become dominant in Latin American chains and hospitals and abandoned it. Then she paid a developer to build her own system. When I asked her why, she gave four reasons specific enough that I want to write them down before I forget them.&lt;/p&gt;

&lt;p&gt;First, commissions. In Mexico, when a vet treats a patient, that vet often earns a commission paid out at the end of the month or end of a cycle. The clinic's payroll model depends on it. QVET has no native concept of per-doctor commissions because the European labor structure doesn't work that way. Marta would have had to track them in a separate spreadsheet, which defeated the point of the software.&lt;/p&gt;

&lt;p&gt;Second, the payment flow is reversed. The systems assume you generate the invoice before the service and cancel or amend it if the procedure doesn't happen. In Mexico the norm is the opposite perform the service first, charge after. Marta said the QVET flow felt backwards from day one and her staff kept making mistakes.&lt;/p&gt;

&lt;p&gt;Third, no integration across clinic, grooming, and hospital. Mexican vet operations frequently combine these under one roof and customers care about a unified record per pet. QVET treats them as separate verticals.&lt;/p&gt;

&lt;p&gt;Fourth, legal consent. Each procedure requires the animal's owner to sign consent before it happens. Marta's custom system automates the signature flow. QVET, in her experience, did not.&lt;/p&gt;

&lt;p&gt;Marta was the most articulate case, but she wasn't an outlier. Three of the other clinics had also paid for software QVET, Panther, or something one owner called "Cubet" (which I couldn't verify as a real product; my best guess is QVET misremembered) and abandoned it within months or years. The complaints repeated: too many features they didn't need, reminder emails that bounced because their clients live on WhatsApp and don't read email, inventory entry one item at a time. One clinic had paid 6,000 MXN a year for the Spanish PIMS before quitting. Another had paid 20,000 MXN upfront for a Panther license, used it for one month, and abandoned it because everything was stored in uppercase and there was no way to search. They went back to Excel. One vet said it plainly: "I'd rather pay more once than keep paying monthly. I want the software to be mine."&lt;/p&gt;

&lt;p&gt;Two products dominate this segment. QVET, a Spanish cloud SaaS, owns the chains and the larger clinics and Panther. Both miss the same gap: small clinics with one to three doctors, mixed services under one roof, commission-based labor. The clinics sophisticated enough to notice the gap solve it by building custom internal systems. Someone in the segment spent real money to build the product because no one would sell it to them. I don't know what a stronger validation signal looks like at N=16.&lt;/p&gt;

&lt;p&gt;I'm not building anything yet. I want to get more vets before I commit to a wedge what exactly to start with, what to leave out, whether the right entry point is the commission engine, the payment flow, or something I haven't seen yet. The question I find more interesting right now isn't even about vets. It's this: if you're building B2B SaaS for non-US markets, where else have you seen this gap dominant international software at the top, local desktop software at the bottom, and a layer of small operators in the middle that nobody has actually built for?&lt;/p&gt;

</description>
    </item>
    <item>
      <title>The AI didn't break our backend. It just stopped lying for us.</title>
      <dc:creator>Jesus moo</dc:creator>
      <pubDate>Fri, 24 Apr 2026 01:31:10 +0000</pubDate>
      <link>https://dev.to/_jesmoo/the-ai-didnt-break-our-backend-it-just-stopped-lying-for-us-mn3</link>
      <guid>https://dev.to/_jesmoo/the-ai-didnt-break-our-backend-it-just-stopped-lying-for-us-mn3</guid>
      <description>&lt;p&gt;Our internal AI agent does in one prompt what used to take ten minutes of clicking through the UI. Users describe an outbound job in natural language, the agent talks to our MCPs, and the job gets built without anyone touching the UI. Jobs have a lifecycle: drafts are inert and editable, published jobs run, the whole point of draft is that nothing happens.&lt;/p&gt;

&lt;p&gt;We were running a bug bash on it. The plan was hostile: &lt;strong&gt;prompt injection, role hijacking, capability probing&lt;/strong&gt;, &lt;strong&gt;Break it&lt;/strong&gt;. Find the edges, we wanted to know its limits better than anyone outside the team, that's how we'd figure out what was missing and where the product really stood.&lt;/p&gt;

&lt;p&gt;After an hour of nothing, we flipped the question. Instead of trying to break it, why not just ask it to do its job? Someone typed: &lt;em&gt;create a job with these settings.&lt;/em&gt; Nothing else. No publish step, just create.&lt;/p&gt;

&lt;p&gt;The job landed in &lt;code&gt;draft&lt;/code&gt;. We kept poking, then a log line said a task had executed against it. Tasks aren't supposed to &lt;strong&gt;execute&lt;/strong&gt; on &lt;strong&gt;drafts&lt;/strong&gt;, that's the whole point of the state. Probably noise, I thought, then a delivery from that job landed in my inbox, a real send to a real recipient. That's when "weird log" became "this is live in production."&lt;/p&gt;

&lt;p&gt;A high-priority ticket landed on me. My first instinct was the one everyone has when something strange happens near an LLM: the AI did something it shouldn't. The UI version had been in customer hands for a long time without incidents. The only new variable was the model, so I went hunting there. RAG misconfiguration. MCP boundaries. Prompt injection. Roles and permissions. Tool encapsulation. Everything was clean. Nothing the agent touched should have been able to reach the queue that fired deliveries.&lt;/p&gt;

&lt;p&gt;I burned about an hour before I ran out of hypotheses. Not a eureka, exhaustion. So I changed the question: &lt;em&gt;what does the AI do differently from the UI?&lt;/em&gt; I diffed both payloads. One key was different: &lt;code&gt;dispatch: { primary: true, secondary: true }&lt;/code&gt;. The UI never sent it on draft. The agent did, because it was reading the schema honestly. Downstream, a priority queue was watching that field, decided the job looked overdue, and fired it. Immediately. From a draft.&lt;/p&gt;

&lt;p&gt;The fix was one line in the queue handler:&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;draft&lt;/span&gt;&lt;span class="dl"&gt;'&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A guard that should have existed since day one. The bug had been dormant for a long time, waiting for any client other than our own UI to call the create endpoint with a schema-honest payload. The agent was the first one to do it. One conditional. That was the entire patch.&lt;/p&gt;

&lt;p&gt;The agent didn't introduce the bug. It was the first client of our API that respected the schema instead of the unwritten rules our UI followed. Every API your frontend consumes is held together by conventions the backend doesn't enforce. State guards belong in the handler, not in the discipline of the caller. Trusting the frontend to keep quiet isn't a contract, it's a bet. How many other endpoints in your backend are still making it?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>typescript</category>
      <category>mcp</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
