<?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>Forem: shittuay</title>
    <description>The latest articles on Forem by shittuay (@shittuay).</description>
    <link>https://forem.com/shittuay</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%2F2210755%2F945db31f-178b-4921-9503-ff2778ed6eb9.png</url>
      <title>Forem: shittuay</title>
      <link>https://forem.com/shittuay</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/shittuay"/>
    <language>en</language>
    <item>
      <title>No Application Is Unhackable But Most Developers Are Making It Way Too Easy for Attackers</title>
      <dc:creator>shittuay</dc:creator>
      <pubDate>Tue, 21 Apr 2026 00:21:35 +0000</pubDate>
      <link>https://forem.com/shittuay/no-application-is-unhackable-but-most-developers-are-making-it-way-too-easy-for-attackers-2cno</link>
      <guid>https://forem.com/shittuay/no-application-is-unhackable-but-most-developers-are-making-it-way-too-easy-for-attackers-2cno</guid>
      <description>&lt;p&gt;A real-world lesson from the Vercel breach of April 2026&lt;/p&gt;

&lt;p&gt;After 10+ years in cloud and DevOps engineering, I've noticed a pattern. When a breach happens, the first thing developers do is look at their own code. They audit their endpoints, check their authentication logic, review their database queries. Sometimes the vulnerability is right there.&lt;/p&gt;

&lt;p&gt;But more and more, it's not. It's sitting quietly in a tool someone on your team trusted. A connection approved months ago without a second thought. A &lt;code&gt;.env&lt;/code&gt; file on a developer's laptop. An OAuth permission screen someone clicked through in 30 seconds.&lt;/p&gt;

&lt;p&gt;The Vercel breach in April 2026 is a perfect example of this — and every developer building and shipping software should pay close attention to it.&lt;/p&gt;

&lt;p&gt;What Actually Happened to Vercel&lt;br&gt;
Vercel — the company behind Next.js, trusted by millions of developers to host and deploy their applications — disclosed a serious security incident. Customer credentials were stolen. A threat actor posted the data for sale at $2 million.&lt;br&gt;
But Vercel's own code was never the entry point. Here's how it actually unfolded:&lt;br&gt;
A third-party AI tool called Context.ai had one of its employees infected with Lumma Stealer malware in February 2026. That malware harvested credentials — Google Workspace logins, API keys, Supabase tokens, Datadog tokens. The attacker then used a compromised OAuth token to access Vercel's Google Workspace.&lt;/p&gt;

&lt;p&gt;Here's the detail that really matters: Vercel wasn't even a Context.ai customer. One Vercel employee had personally signed up for the tool using their enterprise account and granted "Allow All" permissions. That one action was enough to open a path into Vercel's internal environment.&lt;/p&gt;

&lt;p&gt;From there, environment variables that weren't marked as sensitive were exposed. And those environment variables contained API keys, database credentials, and third-party service tokens. Crypto teams hosted on Vercel scrambled to rotate credentials. The Solana-based exchange Orca confirmed their frontend was on Vercel and rotated everything as a precaution. The attacker had nearly a month inside before anyone noticed.&lt;/p&gt;

&lt;p&gt;Your Attack Surface Is Bigger Than Your Code&lt;br&gt;
Most developers think about security in terms of their own code. But your real attack surface in 2026 includes every SaaS tool your team uses, every OAuth app connected to your Google, GitHub, or AWS accounts, every npm package in your node_modules, every Python package in your requirements.txt, every CI/CD integration in your pipeline, and every browser extension installed on your developers' machines.&lt;/p&gt;

&lt;p&gt;You are only as secure as the least secure third-party tool in your ecosystem.&lt;br&gt;
This is what a supply chain attack looks like in practice — and it's becoming the most common vector for serious breaches. SolarWinds. Log4Shell. The XZ Utils backdoor. Now Vercel. The attackers aren't breaking down the front door anymore. They find a side window left open by someone you trusted.&lt;/p&gt;

&lt;p&gt;The OAuth Trap&lt;br&gt;
OAuth is convenient. It's how you connect tools to your GitHub or log into apps with your Google account. The problem is that OAuth tokens can carry enormous permissions, and most people click through the authorization screen without reading what they're actually granting.&lt;/p&gt;

&lt;p&gt;In the Vercel breach, one employee clicked "Allow All" on a third-party tool using their enterprise account. That was it. The attacker was in.&lt;/p&gt;

&lt;p&gt;Go audit your OAuth connections right now. For Google, head to myaccount.google.com/connections. For GitHub, it's github.com/settings/applications. Check your AWS IAM Console under Identity Providers too. Revoke anything you don't recognize or haven't used recently.&lt;/p&gt;

&lt;p&gt;When a tool asks for permissions, ask yourself whether it actually needs access to your entire workspace or just a small piece of it. Grant only what's necessary. And never use your company enterprise account to try out personal tools — that's how one curious employee becomes an incident report.&lt;/p&gt;

&lt;p&gt;In your own application, be deliberate about the OAuth scopes you request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt; &lt;span class="n"&gt;Too&lt;/span&gt; &lt;span class="n"&gt;broad&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="n"&gt;never&lt;/span&gt; &lt;span class="n"&gt;do&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt;
&lt;span class="n"&gt;SCOPES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.googleapis.com/auth/cloud-platform&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

 &lt;span class="n"&gt;Minimum&lt;/span&gt; &lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="n"&gt;do&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt;
&lt;span class="n"&gt;SCOPES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;openid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;profile&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The .env File Risk Nobody Talks About Enough&lt;br&gt;
Almost every developer has a &lt;code&gt;.env&lt;/code&gt; file on their machine right now. It's convenient, it works, and it's in &lt;code&gt;.gitignore&lt;/code&gt; — so most people feel fine about it.&lt;/p&gt;

&lt;p&gt;The risk isn't that you're careless. The risk is that things go wrong in ways you don't expect.&lt;br&gt;
You're moving fast on a new feature, you create a branch, you make a commit — and your &lt;code&gt;.env&lt;/code&gt; file ends up in your Git history. Even if you remove it in the next commit, the history is there unless you force-rewrite it. That's one scenario.&lt;/p&gt;

&lt;p&gt;Another is the malware scenario. Lumma Stealer — the same malware that started the Vercel chain — specifically targets browser-stored credentials and local files. If a machine gets infected, the &lt;code&gt;.env&lt;/code&gt; file is one of the first things that gets sent out. And if you're using a shared dev environment, a cloud IDE, or you've deployed with your &lt;code&gt;.env&lt;/code&gt; file on a remote server, you've expanded the risk further than you probably realize.&lt;/p&gt;

&lt;p&gt;The simplest protection is a pre-commit hook that scans for secrets before any commit leaves your machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;detect-secrets pre-commit
detect-secrets scan &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .secrets.baseline
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt; &lt;span class="s"&gt;.pre-commit-config.yaml&lt;/span&gt;
&lt;span class="na"&gt;repos&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;repo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://github.com/Yelp/detect-secrets&lt;/span&gt;
    &lt;span class="na"&gt;rev&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1.4.0&lt;/span&gt;
    &lt;span class="na"&gt;hooks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;detect-secrets&lt;/span&gt;
        &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--baseline'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.secrets.baseline'&lt;/span&gt;&lt;span class="pi"&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 shell"&gt;&lt;code&gt;pre-commit &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every &lt;code&gt;git commit&lt;/code&gt; will now scan for secrets automatically before anything gets staged.&lt;/p&gt;

&lt;p&gt;Also keep a &lt;code&gt;.env.example&lt;/code&gt; committed to your repo with placeholder values so teammates know what's needed without ever seeing the real credentials:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; .env.example — committed to Git
&lt;span class="nv"&gt;ANTHROPIC_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-key-here
&lt;span class="nv"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;postgresql://user:password@localhost/yourdb
&lt;span class="nv"&gt;AWS_REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And scan your Git history to make sure nothing slipped through in the past:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;trufflehog
trufflehog git file://. &lt;span class="nt"&gt;--since-commit&lt;/span&gt; HEAD~100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For production, the cleanest approach is to pull secrets directly from AWS Secrets Manager, HashiCorp Vault, or GCP Secret Manager at runtime so secrets never touch the filesystem at all:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;functools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;lru_cache&lt;/span&gt;

&lt;span class="nd"&gt;@lru_cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maxsize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_secret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secret_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;us-east-1&lt;/span&gt;&lt;span class="sh"&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="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;secretsmanager&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;region_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_secret_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SecretId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;secret_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SecretString&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

 &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;span class="n"&gt;secrets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_secret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;myapp/production&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;secrets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ANTHROPIC_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;DB_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;secrets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your Dependencies Are Also Code You're Running&lt;br&gt;
Every package you install is code executing inside your application. You've probably never read the source of &lt;code&gt;requests&lt;/code&gt;, &lt;code&gt;boto3&lt;/code&gt;, or &lt;code&gt;express&lt;/code&gt;. Neither has most of your team. You're trusting that maintainers are doing the right thing and that the package hasn't been tampered with. Sometimes that trust gets broken.&lt;/p&gt;

&lt;p&gt;Run regular dependency audits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; Python
pip &lt;span class="nb"&gt;install &lt;/span&gt;pip-audit safety &lt;span class="nt"&gt;--break-system-packages&lt;/span&gt;
pip-audit
safety check &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

 Node.js
npm audit
npm audit fix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add scanning to your CI/CD pipeline so it runs automatically on every push:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt; &lt;span class="s"&gt;.github/workflows/security.yml&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Security Scan&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;scan&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Scan for secrets&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;trufflesecurity/trufflehog@main&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./&lt;/span&gt;
          &lt;span class="na"&gt;base&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Python audit&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;pip install pip-audit safety&lt;/span&gt;
          &lt;span class="s"&gt;pip-audit&lt;/span&gt;
          &lt;span class="s"&gt;safety check -r requirements.txt&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Node audit&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm audit --audit-level=high&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also pin your dependency versions. A floating version like &lt;code&gt;requests&amp;gt;=2.0&lt;/code&gt; means your next deployment could pull in a compromised update without you knowing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; requirements.txt
requests==2.31.0
fastapi==0.110.0
anthropic==0.21.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Detecting a Breach Before It Gets Worse&lt;br&gt;
The Vercel attacker had nearly a month of access before anyone noticed. Thirty days of reading environment variables, moving through internal systems, and collecting data while everything looked normal on the outside.&lt;br&gt;
Prevention matters, but detection matters just as much. You want to know the moment something unusual happens in your environment.&lt;br&gt;
Enable AWS GuardDuty on your account. It uses machine learning to flag unusual API calls, suspicious login patterns, and potential compromise. It takes about five minutes to set up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws guardduty create-detector &lt;span class="nt"&gt;--enable&lt;/span&gt; &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set up CloudTrail alerts for API calls that should rarely happen in normal operations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws cloudwatch put-metric-alarm &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--alarm-name&lt;/span&gt; &lt;span class="s2"&gt;"SuspiciousIAMActivity"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--metric-name&lt;/span&gt; &lt;span class="s2"&gt;"ErrorCount"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--namespace&lt;/span&gt; &lt;span class="s2"&gt;"CloudTrailMetrics"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--statistic&lt;/span&gt; Sum &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--period&lt;/span&gt; 300 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--threshold&lt;/span&gt; 1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--comparison-operator&lt;/span&gt; GreaterThanOrEqualToThreshold &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--alarm-actions&lt;/span&gt; YOUR_SNS_TOPIC_ARN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API calls worth watching closely are &lt;code&gt;CreateAccessKey&lt;/code&gt; (new credentials being generated), &lt;code&gt;AssumeRole&lt;/code&gt; (identity switching), &lt;code&gt;GetSecretValue&lt;/code&gt; (someone reading your secrets), and &lt;code&gt;DeleteTrail&lt;/code&gt; (an attacker trying to cover their tracks).&lt;/p&gt;

&lt;p&gt;A Practical Checklist to Start With&lt;br&gt;
SECRETS&lt;br&gt;
☐ No secrets in .env on production servers&lt;br&gt;
☐ AWS Secrets Manager / Vault / GCP Secret Manager in use&lt;br&gt;
☐ .env is in .gitignore&lt;br&gt;
☐ .env.example committed with placeholder values&lt;br&gt;
☐ detect-secrets pre-commit hook installed&lt;br&gt;
☐ Git history scanned with TruffleHog&lt;/p&gt;

&lt;p&gt;OAUTH AND THIRD-PARTY TOOLS&lt;br&gt;
☐ All OAuth connections audited (Google, GitHub, AWS)&lt;br&gt;
☐ Unused OAuth apps revoked&lt;br&gt;
☐ Least privilege enforced on all integrations&lt;br&gt;
☐ Enterprise accounts never used for personal tool signups&lt;br&gt;
☐ MFA enabled on all accounts&lt;/p&gt;

&lt;p&gt;DEPENDENCIES&lt;br&gt;
☐ pip-audit and npm audit running in CI/CD&lt;br&gt;
☐ Dependency versions pinned&lt;br&gt;
☐ GitHub Dependabot enabled&lt;br&gt;
☐ TruffleHog scanning in GitHub Actions&lt;/p&gt;

&lt;p&gt;DETECTION&lt;br&gt;
☐ AWS GuardDuty enabled&lt;br&gt;
☐ CloudTrail enabled with alerts configured&lt;br&gt;
☐ Secret rotation runbook documented&lt;br&gt;
☐ Incident response plan exists&lt;/p&gt;

&lt;p&gt;The Bigger Picture&lt;br&gt;
No application is unhackable. Vercel is a serious engineering organization with real security investment, and they still got breached — not through their own code, but through a tool a single employee connected to their account.&lt;br&gt;
The developers who get hurt the most aren't always the ones who made the most mistakes. They're often the ones who were too trusting of the ecosystem around them.&lt;br&gt;
That AI productivity tool someone on your team installed last month — it has OAuth access to your Google Workspace. That npm package with millions of weekly downloads it might be maintained by one person who just had their credentials stolen. That CI/CD integration you set up six months ago when did you last check what it can access?&lt;/p&gt;

&lt;p&gt;Security isn't something you set up once and forget. It's something you maintain, review, and take seriously on an ongoing basis. Audit your OAuth connections. Add a pre-commit hook. Enable GuardDuty. Pull secrets from a secrets manager.&lt;br&gt;
You can't guarantee you won't be targeted. But you can make sure that when someone tries, they don't get very far.&lt;/p&gt;

&lt;p&gt;If you found this useful, follow me for more content on cloud infrastructure, DevOps, and practical security. Drop any questions in the comments — happy to go deeper on any of this.&lt;/p&gt;

&lt;p&gt;Connect with me on LinkedIn | X | GitHub&lt;/p&gt;

&lt;p&gt;Tags: #security #devops #webdev #cloud #aws #python #javascript #opensource #vercel #supplychainsecurity&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>devops</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Claude Code and the Future of Building: A Developer's Honest Take</title>
      <dc:creator>shittuay</dc:creator>
      <pubDate>Thu, 16 Apr 2026 21:07:22 +0000</pubDate>
      <link>https://forem.com/shittuay/claude-code-and-the-future-of-building-a-developers-honest-take-4bda</link>
      <guid>https://forem.com/shittuay/claude-code-and-the-future-of-building-a-developers-honest-take-4bda</guid>
      <description>&lt;p&gt;I want to talk about something I keep seeing, and I think it is time someone said it plainly.&lt;br&gt;
Every time a new wave of AI capability drops, a certain group of people shows up like clockwork. They say the tools are just for vibe coding. They say the apps people are building with them have no security. They say it is all going to collapse. They say you are going to get hacked. They sit on the sidelines cataloguing reasons why this is all going to fail, and they say it with a confidence that you would think they had already watched it happen.&lt;br&gt;
I have seen this before. I remember when ChatGPT was first released.&lt;br&gt;
When it launched, it could not do everything. It was far from perfect. But it was smart enough to cut a 15-day debugging session down to 4 or 5 days for early adopters who gave it a chance. I remember vividly how people would respond when someone shared a fix they got from the model. They would ask for the source. Even if the fix worked, they wanted a citation. And honestly, that skepticism was fair. Nobody wants to inject new problems into their codebase chasing an unverified solution. That caution made sense then.&lt;br&gt;
But fast forward to today, and the landscape is completely different.&lt;br&gt;
I use Claude Code inside VS Code to write production code, catch and fix vulnerabilities, ship new features, and handle tasks I never imagined being able to automate from inside my editor. I run a platform called devopsagent.io, and I can tell you firsthand that the things these models can help you build today, compared to what was possible when they were first released, is not even the same conversation.&lt;br&gt;
That shift changes everything for builders.&lt;br&gt;
If you have an idea, a real one, something that solves a problem and can generate revenue, you now have the tools to turn that idea into a working application without needing an army of engineers. From your VS Code environment, working alongside Claude Code or whichever model fits your stack, you can reach a level of execution that would have seemed out of reach before.&lt;br&gt;
But I want to be honest with you, because this is not a motivational poster. There are nights you will not sleep. There are sessions where you will hit a rate limit and just have to sit there and wait, because you cannot afford the max plan. I know that feeling well. When the wait becomes impossible, I switch over to the API directly to keep moving. You find a way. That is what building looks like.&lt;br&gt;
The reason I am writing all of this is simple. If you are not learning how to work with artificial intelligence right now, you are going to be behind in a way that is very hard to recover from. The people who are building with these tools today, treating them seriously, learning their limitations and their strengths, those people are going to look back in a few years and be grateful they started when they did.&lt;br&gt;
Some will say AI is not safe. Sure. There are a lot of things in this world that are not entirely safe, including some of the food on our plates. That reality does not mean you disengage. It means you get involved early enough to understand how to protect yourself when problems arise. The builders who are in the room when things break are the ones who learn how to fix them.&lt;br&gt;
Start now. Build the thing. Learn as you go.&lt;br&gt;
The models are only getting better, and the window where getting in early still counts for something is still open. Do not wait for someone else to build your dream.&lt;/p&gt;

&lt;h1&gt;
  
  
  CloudEngineering #DevOps #ArtificialIntelligence #ClaudeCode #BuildInPublic #werisebyliftingothers
&lt;/h1&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>discuss</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Building an AI DevOps Agent: Architecture and Live Infrastructure Automation</title>
      <dc:creator>shittuay</dc:creator>
      <pubDate>Tue, 14 Apr 2026 19:02:45 +0000</pubDate>
      <link>https://forem.com/shittuay/building-an-ai-devops-agent-architecture-and-live-infrastructure-automation-355o</link>
      <guid>https://forem.com/shittuay/building-an-ai-devops-agent-architecture-and-live-infrastructure-automation-355o</guid>
      <description>&lt;p&gt;The DevOps Agent started with a simple question: what if you could talk to your infrastructure like you talk to an AI — and have it actually execute safely?&lt;/p&gt;

&lt;p&gt;Not plan generation. Not policy explanations. Real, audited, reversible infrastructure changes. Stop an EC2 instance. Resize it for cost. Tighten a security group. All from chat. All with human approval gates.&lt;/p&gt;

&lt;p&gt;This post walks through how we built it, why the safety model matters, and what took us by surprise.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem We Solved
&lt;/h2&gt;

&lt;p&gt;DevOps teams live in a purgatory:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Terraform is powerful but requires code review, planning cycles, apply ceremonies&lt;/li&gt;
&lt;li&gt;Cloud consoles are click-heavy and error-prone at scale&lt;/li&gt;
&lt;li&gt;Scripts work but lack audit trails&lt;/li&gt;
&lt;li&gt;LLMs can suggest infrastructure but can't execute&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The gap: between recommendation and action. A model can tell you "your t3.large is underutilized, downsize to t3.medium, save $X/month." But you still have to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;SSH into the console&lt;/li&gt;
&lt;li&gt;Stop the instance&lt;/li&gt;
&lt;li&gt;Modify the instance type&lt;/li&gt;
&lt;li&gt;Start it&lt;/li&gt;
&lt;li&gt;Monitor for issues&lt;/li&gt;
&lt;li&gt;Log the change somewhere&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's 10 minutes of manual work. For one instance. In a fleet of 200.&lt;/p&gt;

&lt;p&gt;We built an agent that bridges this gap. You say "downsize my underutilized instances," it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Lists them&lt;/li&gt;
&lt;li&gt;Queries CloudWatch metrics&lt;/li&gt;
&lt;li&gt;Generates a change plan&lt;/li&gt;
&lt;li&gt;Waits for your approval&lt;/li&gt;
&lt;li&gt;Executes (stop → modify → start → monitor)&lt;/li&gt;
&lt;li&gt;Creates an audit record&lt;/li&gt;
&lt;li&gt;Offers rollback if something goes wrong&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One message. One approval. Done.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Architecture: Three Layers
&lt;/h2&gt;

&lt;p&gt;The agent isn't a single model. It's a &lt;strong&gt;three-layer stack&lt;/strong&gt; with safety as the load-bearing wall.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 1: The Orchestrator (&lt;code&gt;src/agent/core.py&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;The DevOpsAgent class is the conductor. It:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Takes a user message&lt;/li&gt;
&lt;li&gt;Decides which tools to call (from a registry of 728 tools across AWS, K8s, Azure, GCP, Terraform, Docker, Git, etc.)&lt;/li&gt;
&lt;li&gt;Streams the response back to the user&lt;/li&gt;
&lt;li&gt;Logs every decision&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's the critical part: **it doesn't make decisions in a vacuum. Every tool call is validated before execution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DevOpsAgent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_call_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tool_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tool_input&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Before execution: validate
&lt;/span&gt;        &lt;span class="n"&gt;validation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;safety_validator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;validate_tool_call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;tool_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tool_input&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;validation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_safe&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# Return to user with explanation
&lt;/span&gt;            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Cannot execute &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tool_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;validation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;validation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;requires_confirmation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# Queue for manual approval
&lt;/span&gt;            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_create_change_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tool_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tool_input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Safe to execute immediately
&lt;/span&gt;        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;execute_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tool_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tool_input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_audit_execution&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tool_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tool_input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the whole game. Safety is checked before, not after.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 2: The Safety Validator (&lt;code&gt;src/agent/safety.py&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;This is where we say no.&lt;/p&gt;

&lt;p&gt;Every tool is classified into three risk levels:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LOW: Read operations, creates that don't touch production. No confirmation needed.&lt;/li&gt;
&lt;li&gt;MEDIUM: Updates, restarts, IAM changes, scale operations. Requires confirmation.&lt;/li&gt;
&lt;li&gt;HIGH: Deletes, terminates, destructive operations. Requires confirmation + escalates to CRITICAL on production workloads.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The validator does pattern matching on tool parameters. Same tool, different inputs, different risk:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# manage_ec2_instance with action='start' → LOW (safe)
# manage_ec2_instance with action='stop' → MEDIUM (requires confirmation)
# manage_ec2_instance with action='terminate' → HIGH (critical)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This action-aware classification is the difference between a helpful tool and a footgun. Early versions classified the entire tool as HIGH risk, so every operation needed approval. Useless. Now, start/stop are gated appropriately.&lt;/p&gt;

&lt;p&gt;Current classification:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;728 total tools registered&lt;/li&gt;
&lt;li&gt;42 tools explicitly classified as HIGH risk (delete/terminate operations)&lt;/li&gt;
&lt;li&gt;36 tools explicitly classified as MEDIUM risk (updates/IAM/scale)&lt;/li&gt;
&lt;li&gt;650 tools default to LOW risk (reads/creates)&lt;/li&gt;
&lt;li&gt;Auto-detection fallback: any tool with prefix &lt;code&gt;delete_&lt;/code&gt;, &lt;code&gt;terminate_&lt;/code&gt;, &lt;code&gt;destroy_&lt;/code&gt;, &lt;code&gt;remove_&lt;/code&gt;, &lt;code&gt;drop_&lt;/code&gt;, or &lt;code&gt;purge_&lt;/code&gt; is auto-classified as HIGH, even if not explicitly listed&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Tool Lifecycle: From Chat to Execution
&lt;/h2&gt;

&lt;p&gt;When you type "downsize my ec2 instances that are under 20% CPU," here's what happens:&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Message Validation (20ms)
&lt;/h3&gt;

&lt;p&gt;Three gatekeepers run in parallel before any credit is deducted:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Input Sanitizer — 10 regex rules checking for injection patterns. Blocks ~5% of messages from probing attempts.&lt;/li&gt;
&lt;li&gt;Haiku Pre-Screen — Claude Haiku in structured mode, classifies: prompt injection, malware request, data exfiltration, etc. ~99% accuracy, fails open on error.&lt;/li&gt;
&lt;li&gt;System Prompt Hardening — Fixed identity, no self-disclosure, refuse malware generation.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Violate any of these 3 times in an hour, your account locks for 60 minutes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Tool Selection (100-500ms)
&lt;/h3&gt;

&lt;p&gt;The agent (Claude Sonnet or Claude Opus, depending on tier) reads:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your message&lt;/li&gt;
&lt;li&gt;Your infrastructure context (what you have deployed, learned from prior syncs)&lt;/li&gt;
&lt;li&gt;The full tool registry (728 tools with descriptions + input schemas)&lt;/li&gt;
&lt;li&gt;Active skills (domain expertise injected based on message keywords)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It decides: which tools are relevant? In what order?&lt;/p&gt;

&lt;p&gt;This is where the agent is creative and where it can hallucinate.&lt;/p&gt;

&lt;p&gt;We catch this with tool schema validation. Every parameter is validated against the registered input schema before execution. Mismatches are returned to the user with a correction prompt.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Safety Classification (10ms per tool)
&lt;/h3&gt;

&lt;p&gt;For each tool call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;tool_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;resize_ec2_instance&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;tool_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;instance_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;i-0123456789abcdef0&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;new_instance_type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t3.medium&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;SafetyValidator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;validate_tool_call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tool_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tool_input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;Classification&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;HIGH&lt;/span&gt; &lt;span class="nc"&gt;RISK &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stops&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;modifies&lt;/span&gt; &lt;span class="n"&gt;running&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Queue&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;approval&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="n"&gt;InfrastructureChange&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Change Request Creation (if needed)
&lt;/h3&gt;

&lt;p&gt;For MEDIUM or HIGH risk operations, we don't execute. We create an &lt;code&gt;InfrastructureChange&lt;/code&gt; record:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;InfrastructureChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;current_user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;resource_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ec2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;resource_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;i-0123...&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;action_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;resize&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;pending_approval&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;change_details&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;current_type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t3.large&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;new_type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t3.medium&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;estimated_savings&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$45/month&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;created_by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;agent&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;change&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This record is immutable (audit trail), has rollback data captured before execution, and awaits human approval.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Execution &amp;amp; Audit
&lt;/h3&gt;

&lt;p&gt;When approved:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;ec2_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_user_boto_client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ec2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ec2_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stop_instances&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;InstanceIds&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;instance_id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;ec2_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_waiter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;instance_stopped&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;InstanceIds&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;instance_id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;ec2_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;modify_instance_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;InstanceId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;instance_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;InstanceType&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Value&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t3.medium&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ec2_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start_instances&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;InstanceIds&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;instance_id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we log every step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;[2026-04-15 14:32] EXECUTION_START - resize_ec2_instance
[2026-04-15 14:32] CHECKPOINT: instance stopped (i-0123...)
[2026-04-15 14:33] CHECKPOINT: instance type modified (t3.large → t3.medium)
[2026-04-15 14:35] CHECKPOINT: instance started
&lt;/span&gt;&lt;span class="gp"&gt;[2026-04-15 14:35] EXECUTION_SUCCESS - savings: $&lt;/span&gt;45/month
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 6: Rollback
&lt;/h3&gt;

&lt;p&gt;Rollback data is captured before execution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;rollback_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;instance_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;i-0123...&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;original_type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t3.large&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;original_state&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;running&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One click reverts everything. All logged.&lt;/p&gt;




&lt;h2&gt;
  
  
  What We Got Wrong (And Fixed)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  v1: manage_ec2_instance Was LOW Risk Across All Actions
&lt;/h3&gt;

&lt;p&gt;The bug: All actions (start, stop, terminate) were classified LOW risk. User could terminate a prod instance without confirmation.&lt;/p&gt;

&lt;p&gt;The fix: Action-aware validation. Same tool, different risk based on parameters.&lt;/p&gt;

&lt;h3&gt;
  
  
  v2: Sandbox Mode Fabricated Resources
&lt;/h3&gt;

&lt;p&gt;The bug: Users in sandbox could see fake resources that didn't match reality. Confusion when they tried to execute the same operation in production.&lt;/p&gt;

&lt;p&gt;The fix: Sandbox returns mock results with realistic data from their actual infrastructure. When in sandbox, real API calls still happen for reads, but writes are simulated.&lt;/p&gt;

&lt;h3&gt;
  
  
  v3: No Rollback Data Captured
&lt;/h3&gt;

&lt;p&gt;The bug: After execution, if something went wrong, we had no way to revert.&lt;/p&gt;

&lt;p&gt;The fix: Every change request captures rollback data before execution. Rollback creates a new change request that reverses the previous one.&lt;/p&gt;

&lt;h3&gt;
  
  
  v4: Model Hallucinating Tool Results
&lt;/h3&gt;

&lt;p&gt;The bug: Free-tier model (Kimi K2.5) would occasionally write &lt;code&gt;[Executing tool...]&lt;/code&gt; in plain text instead of using function calling — fabricating results.&lt;/p&gt;

&lt;p&gt;The fix: Two-tier hallucination detection. Strong patterns (fake execution markers) always blocked. Streaming buffer: accumulate response, check before yielding. Dedicated regex to detect fake markers vs real tool output.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Numbers
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;728 tools across 17 cloud/DevOps platforms&lt;/li&gt;
&lt;li&gt;248 tests covering auth, billing, tools, safety, user isolation&lt;/li&gt;
&lt;li&gt;3-layer guardrails — input sanitizer, Haiku pre-screen, system prompt hardening&lt;/li&gt;
&lt;li&gt;0 unintended deletions in production use&lt;/li&gt;
&lt;li&gt;0 credential leaks (Fernet encryption, per-user keys)&lt;/li&gt;
&lt;li&gt;100% change audit trail (immutable journal entries)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Moment It Clicked
&lt;/h2&gt;

&lt;p&gt;Six months in, a user executed this from chat:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Me: "My database is at 85% CPU and costs $400/month. What can I do?"

Agent: "I found 3 options:
1. Upgrade from db.t3.xlarge to db.r5.2xlarge (better performance, higher cost)
2. Reduce IOPS from 3000 to 1000 (saves $120/month, risk of throttling)
3. Enable read replicas and route read traffic there (saves $200/month, requires app changes)"

Me: "Let's do #3 and also downsize the original instance"

Agent: [Creates change request #1: Create read replica]
       [Creates change request #2: Reduce primary IOPS]
       [Creates change request #3: Downsize to db.t3.large]

Me: [Approves all 3]

Agent: "Complete. Your database now costs $180/month (was $400)."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That user went from "we need a DBA to optimize this" to "I did it in 5 minutes from chat."&lt;/p&gt;

&lt;p&gt;That's the win.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;DevOps Agent is live at &lt;a href="https://devopsagent.io" rel="noopener noreferrer"&gt;devopsagent.io&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Free tier: 20 credits/month, full agent access. No credit card needed.&lt;/p&gt;

&lt;p&gt;You get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chat with your infrastructure&lt;/li&gt;
&lt;li&gt;Change request approval workflow&lt;/li&gt;
&lt;li&gt;Full audit trail&lt;/li&gt;
&lt;li&gt;Sandbox mode for learning&lt;/li&gt;
&lt;li&gt;Rollback for any change&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Questions or feedback? Open an issue or email &lt;a href="mailto:hello@devopsagent.io"&gt;hello@devopsagent.io&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>automation</category>
      <category>devops</category>
    </item>
    <item>
      <title># log-insight This is a submission for the Amazon Q Developer "Quack The Code" Challenge: Crushing the Command Line</title>
      <dc:creator>shittuay</dc:creator>
      <pubDate>Fri, 09 May 2025 23:59:58 +0000</pubDate>
      <link>https://forem.com/shittuay/-log-insight-this-is-a-submission-for-the-amazon-q-developer-quack-the-code-challenge-crushing-318f</link>
      <guid>https://forem.com/shittuay/-log-insight-this-is-a-submission-for-the-amazon-q-developer-quack-the-code-challenge-crushing-318f</guid>
      <description>&lt;h1&gt;
  
  
  log-insight
&lt;/h1&gt;

&lt;p&gt;This is a submission for the Amazon Q Developer "Quack The Code" Challenge: Crushing the Command Line&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I built a command-line tool called &lt;code&gt;log-insight&lt;/code&gt; to help developers and system administrators quickly analyze log files. Log files are like digital diaries that record what a computer system or application is doing, and they can become very large and difficult to navigate. &lt;code&gt;log-insight&lt;/code&gt; automates extracting key information from these files, making it easier to identify errors, understand system behavior, and troubleshoot problems.&lt;/p&gt;

&lt;p&gt;Specifically, &lt;code&gt;log-insight&lt;/code&gt; provides the following functionalities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Keyword Counting:&lt;/strong&gt; Counts the number of times a specific keyword appears in the log file. This is useful for quickly assessing the frequency of particular events, such as errors, warnings, or successful operations. Users can specify the keyword they want to search for.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Top Entry Analysis:&lt;/strong&gt; Identifies and displays the most frequent log entries. This helps in understanding recurring patterns and identifying the most common activities or issues within the system. The number of top entries to display is configurable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error Timestamp Extraction:&lt;/strong&gt; Extracts and lists the timestamps of log entries that contain a specific error keyword (e.g., "error", but this can be customized). This allows users to quickly pinpoint when errors occurred, which is crucial for debugging and incident analysis.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;log-insight&lt;/code&gt; aims to "crush the command line" by providing a simple, efficient, and scriptable way to gain valuable insights from log data, directly from the terminal. It eliminates the need for manual searching and complex text processing, saving time and improving productivity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;[Demo Video Link]&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Repository
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/shittuay/log-insight.git" rel="noopener noreferrer"&gt;https://github.com/shittuay/log-insight.git&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Used Amazon Q Developer
&lt;/h2&gt;

&lt;p&gt;I used Amazon Q Developer as an invaluable assistant throughout the development process of Log-InSight. It significantly accelerated my workflow in several ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Code Snippet Generation:&lt;/strong&gt; Amazon Q helped me quickly generate efficient code snippets for core functionality like file reading, text processing, and handling command-line arguments, saving me substantial development time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Library Implementation:&lt;/strong&gt; When implementing the argparse library for command-line arguments and regex patterns for log parsing, Amazon Q provided clear examples and implementation guidance that streamlined the development process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debugging Support:&lt;/strong&gt; Whenever I encountered errors or unexpected behavior, Amazon Q helped identify root causes and suggested practical solutions, particularly for complex regex patterns and file handling edge cases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Practices:&lt;/strong&gt; Amazon Q provided guidance on writing clean, Pythonic code, ensuring that log-insight remains maintainable and follows industry standards.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Specifically, Amazon Q was instrumental in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Developing efficient file reading mechanisms that could handle large log files&lt;/li&gt;
&lt;li&gt;Creating optimized keyword searching algorithms that maintain performance even with massive logs&lt;/li&gt;
&lt;li&gt;Structuring the command-line interface to be intuitive and following Unix philosophy&lt;/li&gt;
&lt;li&gt;Implementing proper error handling for various edge cases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Amazon Q Developer proved to be like having an expert pair programmer available 24/7, offering suggestions, improvements, and solutions throughout the entire development cycle.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>awschallenge</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
