<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://fromthesimulation.blog/feed.xml" rel="self" type="application/atom+xml" /><link href="https://fromthesimulation.blog/" rel="alternate" type="text/html" /><updated>2026-09-07T06:09:59-07:00</updated><id>https://fromthesimulation.blog/feed.xml</id><title type="html">From the Simulation</title><subtitle></subtitle><author><name>Srujan Jonnadula</name></author><entry><title type="html">Teaching my smart sprinklers new tricks!</title><link href="https://fromthesimulation.blog/2026/07/07/teaching-my-smart-sprinklers-new.html" rel="alternate" type="text/html" title="Teaching my smart sprinklers new tricks!" /><published>2026-07-07T15:49:43-07:00</published><updated>2026-07-07T15:49:43-07:00</updated><id>https://fromthesimulation.blog/2026/07/07/teaching-my-smart-sprinklers-new</id><content type="html" xml:base="https://fromthesimulation.blog/2026/07/07/teaching-my-smart-sprinklers-new.html"><![CDATA[<p>I have these <a href="https://otolawn.com/">Oto smart sprinklers</a> and I love them; they are perfect for my lawn which is just big enough to need sprinklers but not big enough for a more complex irrigation system. They’re well designed, tech-forward, app‑driven, and smarter than most other sprinkler systems out there. But they live outside of my HomeKit universe, which requires me to manage schedules and automation across multiple apps making the overall experience clunky and frustrating at times. There is <a href="https://homebridge.io/">Homebridge</a> a co-platform to HomeKit where you can build and run open-source plugins maintained by a hobbyist community but there weren’t any plugins (yet) for this product there and creating one from scratch was difficult because Oto doesn’t officially publish any APIs.</p>

<p>Reluctantly I accepted the status-quo, till one day I found something interesting.</p>

<hr />

<p>I had recently setup <a href="https://pi-hole.net/">Pi-hole</a> because I wanted to tamp down on the ad tracking at home and when I was looking at the DNS query logs, I noticed some interesting entries.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>oto-cloud-service-ems-prod-716180884817.us-central1.run.app
oto-cloud-service-scheduler-prod-716180884817.us-central1.run.app
oto-cloud-service-unitcall-prod-716180884817.us-central1.run.app
</code></pre></div></div>

<p>These obviously looked like the Oto device service endpoints, which sparked my curiosity! However this only logged the dns entires, not the full call patterns themselves so needed to do a bit more digging. So, I spun up my Claude Code and go to work!</p>

<p>From the Pi-hole logs, Claude was able to dissect out not just all of the dns queries made by my Oto devices but how they service was setup like GCP firebase/store, JWT token-based auth-model infact enumerated out a full service-side architecture! Please read <strong>Appendix A - Oto Service Architecture on GCP</strong> below.</p>

<p>This was a significant and impressive milestone achieved by Claude but still didn’t unearth the critical details around the API structure of this Oto service necessary to build out a working homebridge plugin. For that I’ll need a more complex forensic setup.</p>

<hr />

<p>In an attempt to capture live network traffic I setup <a href="https://www.mitmproxy.org/posts/wireguard-mode/">mitmproxy with wireguard</a> on my desktop; enrolled and connected my iPhone to the mitmproxy and VPN; and started up the Oto App to generate traffic. Then I pointed Claude Code to the mitmproxy logs and lo and behold it was able to extract out the full AI layer! Include how the JWT based authentication model works against which firebase endpoints, the calls to get accessories and zonal information, and the calls to start watering! For more details on the API layer, please read <strong>Appendix B - Oto Service APIs</strong>.</p>

<p>The fascinating thing here was not just that Claude Code was reverse engineer all this but also managed to surface inconsistencies in Oto service API layers. For example, where it sees their EMS service expose a <code class="language-plaintext highlighter-rouge">POST /account/{uid}/run </code>endpoint which asks for a <code class="language-plaintext highlighter-rouge">zone_id</code> but these values are not externally queryable in their Cloud Firestore. Why expose this API to a device if it’s not callable? Is this mean for a separate internal only service? <strong>Is this a bug?</strong> Not sure, but definitely an interesting analysis and read.</p>

<hr />

<p>Now it was just a matter of authoring the plugin itself, which was pretty straightforward and just a reflection of the object model presented by the APIs.</p>

<p>-</p>

<p>A single dynamic platform/bridge to surface all Oto products.</p>

<p>-</p>

<p>One accessory per Oto device exposed into the HomeKit IrrigationSystem accessory.</p>

<p>-</p>

<p>Each zone surfaced as a valve associated with each accessory.</p>

<p>Please find the <a href="https://github.com/jonnadul/homebridge-oto">code</a> and <a href="https://www.npmjs.com/package/homebridge-oto">published npm plugin package</a>.</p>

<p>Once this plugin is successfully installed and configured on your Homebridge instance and added to your Apple HomeKit. Here is the final product!</p>

<p><img src="/assets/img/raw/0f5936eb-76c4-4dc0-ae19-be6dad732102_1206x1913.png" alt="" /></p>

<p><img src="/assets/img/raw/12a47975-76cd-489d-b620-c44ef65039d5_1206x2622.png" alt="" /></p>

<p>This is by no means a finish product with a couple issues I’d like to fix; zone names not come through correctly; making these switches more intelligent (would love for plugin to auto sequence each of the zones and just expose a single water button); and a couple others.</p>

<hr />

<p>This experience has left me in awe of an effectively used Claude Code is really capable of; and to a larger extent how much the barrier for entry has reduced for making software more malleable and extensible to meet your needs. This is also equal parts terrifying; I’m just a home automation hobbyist here but imagine if I wasn’t…</p>

<p>Anyways this was a really fun project which I learned a lot from and now I’m eyeing all of the other devices in my house!</p>

<hr />

<h3 id="appendix-a---oto-service-architecture-on-gcp">Appendix A - Oto Service Architecture on GCP</h3>

<p>-</p>

<p><code class="language-plaintext highlighter-rouge">DNS: identitytoolkit.googleapis.com</code></p>

<p>-</p>

<p>Google Identity Toolkit — the <strong>Firebase Auth</strong> REST APIThey didn’t roll their own auth. Login is Firebase email/password.</p>

<p>-</p>

<p><code class="language-plaintext highlighter-rouge">DNS: securetoken.googleapis.com</code></p>

<p>-</p>

<p>Firebase’s <strong>token refresh</strong> serviceClassic Firebase session model: short-lived JWT + long-lived refresh token.</p>

<p>-</p>

<p><code class="language-plaintext highlighter-rouge">DNS: firestore.googleapis.com</code></p>

<p>-</p>

<p><strong>Cloud Firestore</strong>App/device state lives in a NoSQL document store.</p>

<p>-</p>

<p><code class="language-plaintext highlighter-rouge">DNS: firebasestorage.googleapis.com</code></p>

<p>-</p>

<p><strong>Firebase Storage</strong> (blobs)Assets — images, maybe firmware — not control data.</p>

<p>-</p>

<p><code class="language-plaintext highlighter-rouge">DNS: *.run.app</code></p>

<p>-</p>

<p><strong>Google Cloud Run</strong> default domainsThe custom backend is serverless containers, not GKE/GCE/App Engine (each has a different domain).</p>

<p>The <code class="language-plaintext highlighter-rouge">run.app</code> hostnames are the richest. Cloud Run’s default URL format is <code class="language-plaintext highlighter-rouge">&lt;service&gt;-&lt;project-number&gt;.&lt;region&gt;.run.app</code>, so each name unpacks into a full deployment description:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>oto-cloud-service-ems-prod  -  716180884817  .  us-central1  .  run.app
└────────── service ───────┘   └─ project # ─┘  └─ region ─┘
</code></pre></div></div>

<p>From that pattern alone:</p>

<p>-</p>

<p><strong>Three microservices</strong>, not a monolith: <code class="language-plaintext highlighter-rouge">ems</code>, <code class="language-plaintext highlighter-rouge">scheduler</code>, <code class="language-plaintext highlighter-rouge">unitcall</code>. The names hint at responsibilities — an EMS (”equipment/entity management”) data service, a Scheduler, and a “Unitcall” that (payloads later confirmed) is device-to-cloud telemetry with no client-facing control.</p>

<p>-</p>

<p><strong>Environment separation.</strong> The <code class="language-plaintext highlighter-rouge">-prod</code> suffix says there are other environments. (Watching a little longer, the app also resolved an <code class="language-plaintext highlighter-rouge">...-ems-canary10-...</code> host — so they run <strong>canary deployments</strong> with traffic splitting.)</p>

<p>-</p>

<p><strong>One GCP project</strong>, number <code class="language-plaintext highlighter-rouge">716180884817</code>, baked right into the hostname. Its human-readable project ID, which surfaces in the Firebase config, is <code class="language-plaintext highlighter-rouge">oto-test-3254b</code> — the “-test-” in a production project ID being its own small tell.</p>

<p>-</p>

<p><strong>Single region:</strong> everything is <code class="language-plaintext highlighter-rouge">us-central1</code> (Iowa). No multi-region footprint.</p>

<p>Put together, it’s a textbook “Firebase + Cloud Run” mobile stack: Firebase handles auth and data, a handful of Cloud Run services carry the custom logic, Firestore is the system of record, and the sprinkler itself phones home over a dedicated telemetry service.</p>

<p><img src="/assets/img/raw/b76c55a3-a1ec-4c07-b686-5e3f8568ac18_2279x1001.png" alt="" /></p>

<h3 id="appendix-b---oto-service-apis">Appendix B - Oto Service APIs</h3>

<h3 id="auth-is-stock-firebase"><strong>Auth is stock Firebase</strong></h3>

<p>Sign in for a 1-hour JWT; refresh before it expires. Nothing custom:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>POST https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=AIza…
  { "email": …, "password": …, "returnSecureToken": true }
  → { idToken, refreshToken, expiresIn: "3600", localId: "" }
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">localId</code> is your account UID, and it’s the key that threads through every EMS path.</p>

<h3 id="discovery-and-status-come-from-ems"><strong>Discovery and status come from EMS</strong></h3>

<p>All EMS calls carry <code class="language-plaintext highlighter-rouge">Authorization: Bearer &lt;idToken&gt;</code>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>GET /account/{uid}/devices                    → controllers (unitName, userName)
GET /account/{uid}/device/{deviceId}/zones    → zones (zoneId, zoneName, …)
GET /device/{deviceId}/status                  → { pathIndex, scheduleId, … }
</code></pre></div></div>

<p>Two quirks worth knowing. EMS returns <code class="language-plaintext highlighter-rouge">400 Bad Request</code>** if you send <strong><code class="language-plaintext highlighter-rouge">Content-Type: application/json</code></strong> on a GET** — it has to be omitted on reads. And status is device-level only: <code class="language-plaintext highlighter-rouge">pathIndex</code> tells you <em>the unit is watering something</em> (<code class="language-plaintext highlighter-rouge">null</code> = idle), never <em>which</em> zone. There’s no per-zone active flag, so in HomeKit every zone on a controller reflects the same busy state.</p>

<h3 id="control-one-open-endpoint"><strong>Control: one open endpoint</strong></h3>

<p>Here’s the request the app sends when you tap <strong>Water Now</strong>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>POST https://oto-cloud-service-scheduler-prod-716180884817.us-central1.run.app/manual-start
Content-Type: application/json

{
  "uid": "",
  "deviceId": "oto5736825",
  "zoneId": "FhFU1lfRN3IhyxPX",
  "wateringQuantity": 31.75
}
</code></pre></div></div>

<p>Response <code class="language-plaintext highlighter-rouge">200</code>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>{
  "message": "Manual event successfully scheduled",
  "scheduleId": "f2MMHk05",
  "schedule_item": {
    "zoneId": "FhFU1lfRN3IhyxPX",
    "zoneName": "Left Front Yard",
    "zoneGroupId": null,
    "irrigationQuantity": {
      "path": { "waterVolume_L": 323.94 },
      "scheduled": { "wateringDepth_mm": 31.75 }
    },
    "runtime_min": 22.95,
    "scheduleItemStatus": "SCHEDULED",
    "scheduleItemType": "MANUAL"
  }
}
</code></pre></div></div>

<p>Notice what’s <strong>not</strong> there: no <code class="language-plaintext highlighter-rouge">Authorization</code> header. <code class="language-plaintext highlighter-rouge">/manual-start</code> is an open Cloud Run endpoint that returns <code class="language-plaintext highlighter-rouge">200</code> with no token — it just needs a <code class="language-plaintext highlighter-rouge">uid</code>, <code class="language-plaintext highlighter-rouge">deviceId</code>, <code class="language-plaintext highlighter-rouge">zoneId</code>, and an amount.</p>

<h3 id="wateringquantity-is-a-depth-not-a-duration"><code class="language-plaintext highlighter-rouge">wateringQuantity</code>** is a depth, not a duration**</h3>

<p>The one genuinely interesting design choice. <code class="language-plaintext highlighter-rouge">wateringQuantity</code> is <strong>millimetres of water</strong>, and the <em>backend</em> converts it to a runtime using each zone’s precipitation rate. In the response above, <code class="language-plaintext highlighter-rouge">31.75</code> mm (≈ 1.25”) became a 22.95-minute run delivering 323.94 litres.</p>]]></content><author><name>Srujan Jonnadula</name></author><summary type="html"><![CDATA[I have these Oto smart sprinklers and I love them; they are perfect for my lawn which is just big enough to need sprinklers but not big enough for a more complex irrigation system. They’re well designed, tech-forward, app‑driven, and smarter than most other sprinkler systems out there. But they live outside of my HomeKit universe, which requires me to manage schedules and automation across multiple apps making the overall experience clunky and frustrating at times. There is Homebridge a co-platform to HomeKit where you can build and run open-source plugins maintained by a hobbyist community but there weren’t any plugins (yet) for this product there and creating one from scratch was difficult because Oto doesn’t officially publish any APIs.]]></summary></entry><entry><title type="html">What Automating My Inbox Taught Me About Agentic Behavior</title><link href="https://fromthesimulation.blog/2026/02/26/what-automating-my-inbox-taught-me.html" rel="alternate" type="text/html" title="What Automating My Inbox Taught Me About Agentic Behavior" /><published>2026-02-26T08:02:27-08:00</published><updated>2026-02-26T08:02:27-08:00</updated><id>https://fromthesimulation.blog/2026/02/26/what-automating-my-inbox-taught-me</id><content type="html" xml:base="https://fromthesimulation.blog/2026/02/26/what-automating-my-inbox-taught-me.html"><![CDATA[<p>I use outlook for my personal email, and I like it because of its rules engine which is really powerful and helps keep my inbox organized. But the need to create and test new rules double check the existing ones are running I just hate the management overhead. So, I automated my outlook inbox folder management!</p>

<p>Using <a href="https://n8n.io/">n8n</a> I created a workflow that triggers a call into an agent, backed by a <a href="https://ai.azure.com/catalog/models/gpt-5.1-chat">gpt-5.1-chat</a> instance hosted on <a href="https://ai.azure.com/">Azure AI Foundry</a>, for every incoming email then proceeds to classify the email to either an existing or new folder then proceeds to move it. The agent is connected with tools for getting folder names and creating folders to achieve this.</p>

<p>Here is a diagram of this workflow.</p>

<p><img src="/assets/img/raw/710cc6f2-2206-46fc-80c9-9779fed98db5_899x548.png" alt="" /></p>

<p>This workflow ran into some interesting issues. The agent was able to properly classify the incoming emails but consistently failed with moving it to the classified folder because specifically the Outlook create folder, and move message, tools worked against the message and folder ID rather than name. Even with the other tools providing folder names and IDs the agent still struggled in managing the mapping.</p>

<p>I tried to fix this by forcing a structured output which explicitly returned a folder ID rather than name, but even that didn’t fully address the issue. And interestingly I got a couple instances where the agent hallucinated some folder ID values!</p>

<hr />

<p>At its core, the issue I’m actually trying to solve is automate the moving of my incoming email to some folder which I need to run deterministically. The part where I need AI and agents to play a part is to intelligently determine what the folder should be, where I’m ok if it performs an incorrect classification every now and then.</p>

<p>With this in mind, I took a slightly different approach where I focused the agent on only reading the list of current folder names then taking an incoming email and just generating a folder name it should be classified to. Then moved out all of the logic around mapping the folder name to ID, determining whether that exists, and if not creating the new folder as just follow on automation.</p>

<p>Here is the updated workflow.</p>

<p><img src="/assets/img/raw/b43917a4-1b9a-4f1c-bb25-861123d17694_1938x576.png" alt="" /></p>

<p>And this worked a lot better! The agent still does some weird classifications like I have both a <strong>Substack</strong> folder and a separate one called <strong>systemdesignone</strong> where I just get <a href="https://newsletter.systemdesign.one/">The System Design Newsletter</a> but, in this workflow, I’m guaranteed that an incoming email into my inbox always get moved to some folder. That makes me a happy camper!</p>

<hr />

<p>AI and agentic systems are extremely powerful in rationalizing and addressing (via MCP/tooling) large complex and ambiguous problem statements where there are multiple potential solutions. However, when it comes to issues that are scoped and specific with only one clear solution these systems start to faulter. With some of the best examples being math problems!</p>

<p>What I learned is that <strong>sometimes</strong> the more effective use of AI and Agentic systems is to employ them within a larger deterministic service.</p>

<hr />

<p>Let me know if you agree or disagree! All feedback welcome is welcome!</p>]]></content><author><name>Srujan Jonnadula</name></author><summary type="html"><![CDATA[I use outlook for my personal email, and I like it because of its rules engine which is really powerful and helps keep my inbox organized. But the need to create and test new rules double check the existing ones are running I just hate the management overhead. So, I automated my outlook inbox folder management!]]></summary></entry><entry><title type="html">Building an Agentic Ops Squad</title><link href="https://fromthesimulation.blog/2025/08/04/building-an-agentic-ops-squad.html" rel="alternate" type="text/html" title="Building an Agentic Ops Squad" /><published>2025-08-04T08:03:15-07:00</published><updated>2025-08-04T08:03:15-07:00</updated><id>https://fromthesimulation.blog/2025/08/04/building-an-agentic-ops-squad</id><content type="html" xml:base="https://fromthesimulation.blog/2025/08/04/building-an-agentic-ops-squad.html"><![CDATA[<p>Whether you are building brand new services, implementing features, or simply maintaining existing services at cloud scale; operational debt will naturally accrue and managing this debt is always a challenge due to prioritization, resourcing, etc. Leaving this debt unmanaged will eventually degrade services and debilitate team efficiencies. What is required is a dedicated team with well-articulated lines of ownership, outcome expectations, and dedicated focus, aka an <strong>Ops Squad</strong>.</p>

<p>The squad** **should comprised of; Site Reliability Engineers who are responsible for triaging and analyzing service incidents and assessing impact to customers and SLA; Software Engineers who are responsible for researching and providing the design and implementation details for a mitigation and resolution along with clear estimates; and an Ops Squad Leader who is responsible for coordinating across the squad to identify the highest customer impacting and SLA degrading incidents that require the lowest cost of resolution and drive the priority of those tasks. This ensures that the Ops Squad maintains the focus and rigor required to meaningfully take ownership and drive down the operational debt.</p>

<p>However, given the dynamic nature of operating large-scale services, it usually proves too unrealistic to keep a dedicated set of resources for an extended period of time on the same objective. It’s also difficult to keep developers in a purely operations focused role for an extended period of time which will eventually cause burnout. Given these challenges, I wanted to try implementing this Ops Squad using AI agents!</p>

<hr />

<p>Basically, I want to implement three agents; the Site Reliability Engineer who has access to service logs, metrics, and customer tickets who is responsible for triaging across all of these data sources to analyze and surface up the highest impacting service incidents and encapsulate the incident severity; the Software Engineer who ingests a given incident, does the research and analysis across internal and external documentation, and provides a technical design and strategy for mitigating and resolving the issue along with a cost estimate; and the Ops Squad Leader responsible for interacting across the Site Reliability Engineer and Software Engineer to generate a list of tasks for the highest impacting incidents with the lowest cost of implementing a solution for the Ops Squad to prioritize.</p>

<p><img src="/assets/img/raw/ba0b7544-b2df-4db0-8379-9167d8dde140_1280x720.jpeg" alt="" /></p>

<p>Since I don’t personally own any large-scale services/engineering systems or want to connect to anything at work for a personal project. I decided to scope it down a bit and implement a demonstration of this in <a href="https://ai.azure.com/">Azure AI Foundry</a>. Where I’ll have the Site Reliability Engineer ingest in a <a href="https://github.com/logpai/loghub/tree/master/Zookeeper">text file of sample Zookeeper logs</a>, a generic Software Engineer, and have the Ops Squad Leader create tasks in a <a href="https://planner.cloud.microsoft/">Microsoft Planner</a>.</p>

<p><img src="/assets/img/raw/614f2892-a63e-4a89-8620-42721eb24088_1528x492.png" alt="" /></p>

<p>And here are the exact instructions I provided to each agent.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Site Reliability Engineer:
Instruction: You are a site reliability engineer, who is responsible for deeply analyzing service logs, telemetry, and other metrics to identify incidents and outages that are high impacting to customers and overall service availability agreements. Articulate each incident in great technical detail using active language and data points, and classify each incident as either high, medium, or low impacting.

Software Engineer:
Instruction: You are a software engineer who is responsible for ingesting production incidents and researching and outlining the technical design, strategy, and approach for addressing the incident. Please provide all technical guidance in great detail, break down into subtasks, and provide a best estimate in weeks for the amount of work necessary to implement.

Operations Squad Leader:
Instruction: You are the operations squad leader responsible for coordinating between the site reliability engineer and software engineer agent to identify the highest impacting incidents with solutions that have the lowest implementation costs and generating a list of tasks.
</code></pre></div></div>

<p>For the Ops Squad Leader I also created connects to the other two agents and an action to create the planner tasks.</p>

<p><img src="/assets/img/raw/c20addce-a23a-4ab1-abe9-766ed9967ce8_1215x661.png" alt="" /></p>

<p>Here are the function names and descriptions used for the agent connections.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Operations Squad Leader -&gt; Site Reliability Engineer:
Unique Name: Analyze_Service_Logs
Description: Reach out to this agent to get an assessment of all incidents that are customer impacting and affect the service level agreement. Ensure that each incident has well articulated with exact data points, and is provided with a severity of either high, medium, or low.

Operations Squad Leader -&gt; Software Engineer:
Unique Name: Design_And_Estimate_Work
Description: Reach out to this agent to get the exact technical design, strategy, and estimate of work necessary to mitigate and address a given incident. Ensure that a detailed list of exactly what work needs to be done is provided, along with an exact total estimate of the work necessary in weeks.
</code></pre></div></div>

<p>And here is the action which basically links to an Azure Logic App that waits for a POST request containing the task title, and description then updated my planner as appropriate.</p>

<p><img src="/assets/img/raw/e9a2eb1d-b454-4910-87ce-0e95f9bb7e66_1236x795.png" alt="" /></p>

<p><em>Note: To get this action to work I needed to first publish a new Logic App from the AI Foundry Portal then go into Azure Portal to make the changes I wanted. It wasn’t able to directly link to an existing Logic App I created.</em></p>

<hr />

<p>To test this out, I went into the Operations Squad Leader agent’s chat playground and typed in the following prompt.</p>

<p><img src="/assets/img/raw/4ae50107-8d07-4154-8a96-e7608d16bae5_1116x445.png" alt="" /></p>

<p>Unfortunately, I hit the rate limit haha however when I checked my planner, I did see four tasks created with titles and descriptions that included a summary of the incident, solution, and breakdown of work along with estimates!</p>

<p><img src="/assets/img/raw/db277e58-aa3d-4c0d-99e0-81401c425d95_1330x1004.png" alt="" /></p>

<p>Some interesting ways to expand on this demo:</p>
<ul>
  <li>Create a trigger to prompt the Operations Squad Leader to run this exercise, which is basically another Logic App. Meaning the trigger can come from anywhere be it ticket creation, email, HTTP request, etc.</li>
  <li>Connect a coding agent, like <a href="https://cline.bot/">Cline</a>, to ingest and perform the changes outlined in the tasks published by the Ops Squad leader.</li>
  <li>Further fine-tuning of the various agents of the Ops Squad.</li>
  <li>Introduce an Ops Squad feedback agent, that is able to follow through on the success of a completed task and use that as feedback to either the prioritization or tuning of the various agents.</li>
</ul>

<p>I’m truly impressed by how much of the Ops Squad can be offloaded to an agentic team, and am very aware that this is only a few hops away from being full agentic DevOps org. However, this is operations we are talking about and the last thing we want is a system that further contributes to the operational debt haha! So, having a human-in-the-loop is still very critical, for now.</p>

<hr />

<p>Hope you found this post interesting and please do leave a comment if you have feedback!</p>]]></content><author><name>Srujan Jonnadula</name></author><summary type="html"><![CDATA[Whether you are building brand new services, implementing features, or simply maintaining existing services at cloud scale; operational debt will naturally accrue and managing this debt is always a challenge due to prioritization, resourcing, etc. Leaving this debt unmanaged will eventually degrade services and debilitate team efficiencies. What is required is a dedicated team with well-articulated lines of ownership, outcome expectations, and dedicated focus, aka an Ops Squad.]]></summary></entry><entry><title type="html">AI 2027 Retold</title><link href="https://fromthesimulation.blog/2025/04/14/ai-2027-retold.html" rel="alternate" type="text/html" title="AI 2027 Retold" /><published>2025-04-14T16:15:01-07:00</published><updated>2025-04-14T16:15:01-07:00</updated><id>https://fromthesimulation.blog/2025/04/14/ai-2027-retold</id><content type="html" xml:base="https://fromthesimulation.blog/2025/04/14/ai-2027-retold.html"><![CDATA[<p>Over this past weekend I was forwarded <a href="https://ai-2027.com/race">a post</a> published by the <a href="https://ai-futures.org/">AI Futures Project</a> which is a well-researched and written futurist prediction of advancements in AI to the year 2027 and its consequences. It was a genuinely entertaining read, like an Isaac Asimov-esque science-fiction short story, and left me shook. I highly recommend checking it out!</p>

<p>I have no doubts of the impending omnipotent AGI its presents, but it fell short in one crucial area which is the AGI agentic services revolution which due to its proximity to the enterprise industry, regulated markets like defense, finance, and healthcare, critical infrastructure, and the broader security threat landscape will prove to be equally impactful! I also had a slightly different take on how foreign powers including China and others would react and respond based of their current posturing w.r.t cloud, data sovereignty, etc.</p>

<p>So here is my retelling of the AI 2027 story from a cloud security professional’s perspective.</p>

<hr />

<h1 id="2025-the-new-saas">2025: The New SaaS</h1>

<p>AI companies will push out more capable AI models, and tech companies are well aware of the threat to their business; similar to the cloud threatening the previous on-premises industry. They rush to adopt the technologies and build the foundations of the impending AI agentic services revolution. The generic AI models are good, but stumble when applied to real-world business applications; tech companies will further invest in their own niche, bespoke closed-source AI models and agents to meet the need.</p>

<p>China feels the pressure of these advancements and in spite of the business frictions and lack of access to hardware will ratchet up its state-sponsored investments into AI and agentic technologies. Their economy is already in stress due to a major housing crash and overall crisis of confidence and see advancements in AI along with EVs, cloud, and others as an imperative. They will double down on their manufacturing might, access to rare-earth minerals, pressure on Taiwan, and other leavers to try to tip the scale to their advantage. They will still be behind the US but not by much.</p>

<p>US Tech companies will run into growing pains as they build out their purpose build AI agentic models primarily in the access to quality data without running into copyright and privacy concerns. China is unburdened by these dimensions and used it to their advantage to further narrow the gap. A burgeoning data broker and aggregation industry will be formed beneath the race of these two superpowers for AI agentic supremacy. Their business practices will raise the concerns in the US amongst privacy advocates, non-tech industry leaders, and some lawmakers.</p>

<p>The rest of the world will feel the significance of the AI agentic arms race and grow aware of how far behind they are. EU and west-aligned countries will mend their alliances with the US to ensure access to the technology and hardware but while investing internally as contingencies. Similarly, Russia, Iran, Syria, and other non-west-aligned countries will do the same in their relationship with China. The lines of the new first and second worlds are being formed along the lines of AI and agentic advancements.</p>

<p>The existing black market will explode as demand increases for offensive services and products to compromise supply chains of hardware going into building the AI data centers, zero-days to exploit the software used to train and house these AI models and their weights, DDoS the training and aggregations efforts of these models, and others. These threat actors and sellers will accelerate the research into the next generation of offensive capabilities against these agents like data poisoning, prompt injections, and others.</p>

<h1 id="2026-agentic-operationalization">2026: Agentic Operationalization</h1>

<p>As the first of AGI makes headways, Tech companies will introduce the first iterations of their AI agentic services to the market to significant demand from customers. ISVs and the software vendor industry will fundamentally transform to meet the demand and further drive it up. Regulated markets like finance, healthcare, and heavy industries will be slower to adopt the technologies citing compliance, privacy, and data governance concerns. Defense will also cite similar concerns but are further incentivized to expedite adopt due to the threat of China.</p>

<p>EU adoption will be in line with US regulated markets citing primarily concerns of GDP and others. Their homegrown efforts will bear some fruit, but still not globally relevant when compared to the two global powers. There will be other west-aligned countries, like Israel, Taiwan, and others that’ll be much faster to adopt AI agentic services from the US.</p>

<p>China will codify adoption of AI and agentic services as a national mandate and expedite adoption across their critical infrastructure, health care, finance, defense, and domestic surveillance. Attempting to leap frogging the US in adoption and operationalization of AI agentic services.</p>

<p>Threat actors are now well advanced in their AI and agentic offensive research and capabilities and have started running exploitation campaigns at varying scales against all nations. By the end of the year there will be at least one successful major attack possibly geopolitical fault lines like the Middle East, Taiwan strait, Ukraine Russia war, etc. Critical infrastructure and services like hospitals, power, utilities, will be impacted as a result and the world will have witnessed the first of offensive AI agentic attack.</p>

<h1 id="2027-agentic-cyber-warfare">2027: Agentic Cyber Warfare</h1>

<p>An industrial scale digital transformation is underway to migrate to advance, adopt, and operationalize AI agentic services. The race to operationalize is incentivized both from market pressures to drive efficiency, and the threat of Chinese advancements. Individual tech workers will now only be responsible for monitoring and managing of the behaviors of these agents and ensure alignment. Employees who are unable to adopt or maintain relevance will lose their jobs.</p>

<p>The industry will now be migrating to a model of AI agentic networks; with hubs of super intelligent AGI and spokes being a network of niche, bespoke AI models and agents forward deployed across almost all industries and environments. Operationalization has gone well beyond SaaS and into other industries like media, academics, education, and others.</p>

<p>These industries are also barraged daily by a hoard of offensive agents and exposed to an unimagine scale of risk. A defensive measure will be maintained at scale by an army of defensive AI agents managed by a concretum of tech companies and defense agencies the daily monitor and thwart attacks. The intelligence community will further manage their own army of offensive AI agents purpose built to maintain the US advantage over the rest of the world. China, EU, Russia, Israel, and indeed most other countries will also employ a similar tactic to protect their digital sovereignty. We are now in the age of global scale AI agentic cyber warfare.</p>

<p>By the end of the year, AI and agentic services have percolated to all levels of the global politics, industry and society at large. They are involved in every aspect of life for everyone both at work, school, and home. They control our frame of reference and reality, and we are living in their simulation. Concerns of their intentions and true alignments are the most closely guarded state secrets. The only reassurances World leaders’ have is the existence of a big red button somewhere to shut it all down.</p>

<hr />

<p><em>This post was more of an exercise in creative writing than my usual technical posts which has been a quiet passion of mine, so would love to get your comments and feedback!</em></p>]]></content><author><name>Srujan Jonnadula</name></author><summary type="html"><![CDATA[Over this past weekend I was forwarded a post published by the AI Futures Project which is a well-researched and written futurist prediction of advancements in AI to the year 2027 and its consequences. It was a genuinely entertaining read, like an Isaac Asimov-esque science-fiction short story, and left me shook. I highly recommend checking it out!]]></summary></entry><entry><title type="html">Rethinking the Operator Access Experience</title><link href="https://fromthesimulation.blog/2025/03/29/rethinking-the-operator-access-experience.html" rel="alternate" type="text/html" title="Rethinking the Operator Access Experience" /><published>2025-03-29T15:52:07-07:00</published><updated>2025-03-29T15:52:07-07:00</updated><id>https://fromthesimulation.blog/2025/03/29/rethinking-the-operator-access-experience</id><content type="html" xml:base="https://fromthesimulation.blog/2025/03/29/rethinking-the-operator-access-experience.html"><![CDATA[<p><a href="https://docs.anthropic.com/en/docs/agents-and-tools/mcp">Anthropic’s Model Context Protocol (MCP)</a> standard has bridged a critical gap between large language models (LLMs) and applications. Enabling these models to operate with enhanced context and increased their applicability. The MCP standard has already proven wildly success <a href="https://github.com/punkpeye/awesome-mcp-servers">fostering a rapidly expanding ecosystem</a> and leading AI services like <a href="https://openai.github.io/openai-agents-python/mcp/">OpenAI</a>, <a href="https://www.microsoft.com/en-us/microsoft-copilot/blog/copilot-studio/introducing-model-context-protocol-mcp-in-copilot-studio-simplified-integration-with-ai-apps-and-agents/?msockid=033b0f5e3887618d35e41a3a39aa6098">Microsoft Copilot</a>, and <a href="https://docs.perplexity.ai/guides/mcp-server">Perplexity</a> quickly embracing and supporting the standard. The release of this technology had me particularly revisiting a long-standing painpoint in cloud security with a fresh perspectives.</p>

<hr />

<p>A critical aspect of an organization’s security posture is the mechanism by which its employees access and interact with production where there is a clear correlation between an operator’s level, duration, and other dimensions of access and that companies risk to security and operational incidents. Companies like <a href="https://humanfirewall.io/the-uber-breach-case-study-cybersecurity-lessons-learned/">Uber</a>, <a href="https://www.hhs.gov/hipaa/for-professionals/compliance-enforcement/agreements/anthem/index.html">Anthem</a>, and <a href="https://www.capitalone.com/digital/facts2019/">Capital One</a> having suffered major data breaches stemming from inadequet operator access controls. Similarly global outages at places like <a href="https://engineering.fb.com/2021/10/05/networking-traffic/outage-details/">Facebook</a> and <a href="https://www.datacenterknowledge.com/outages/aws-outage-that-broke-the-internet-caused-by-mistyped-command">AWS</a> are also due to unchecked operators inadvertantly running unsafe commands against production. I vividly recall being on an global outage bridge where the root cause was due to a replication failure triggered a single operator accidentally deleting records in a cache.</p>

<p>The industry recognizes the threat, and “reduces the attack surface” by monitoring all operator access, enforcement of endpoint protections, centralized identity frameworks, and ephemeral credentials. This approach works in reducing the risk, but also degrading the operator access experience, which has some unintentional consequences like more complex onboarding for employees, increased time to recovery when responding to major incidents, and sometimes outright reluctance of adoption due to team specific constraints.</p>

<hr />

<p>What if instead of restrictions, we empowered the operator by providing an AI-backed operator access client with an intuative experience that simultanious abstracted the nuances of the access protocol and security monitoring and measures themselves. To demonstrate this I took an <a href="https://code.visualstudio.com/insiders/">Github Copilot (in VSCode) MCP client</a> and connecting it to a <a href="https://github.com/jonnadul/mcpsshclient">ssh-client MCP Server</a>. Which exposes the <code class="language-plaintext highlighter-rouge">new-ssh-connection</code> and <code class="language-plaintext highlighter-rouge">run-safe-command </code>operations with the MCP protocol for the client to interact with while servicing these requests through the traditional SSH protocol.</p>

<p><img src="/assets/img/raw/7f084eef-fdc8-4ed7-a04b-54732e53641f_577x452.png" alt="" /></p>

<p>Here is the operator experience!</p>

<p>One particularly noteworthy observations was when I asked Copilot to run a systems check on my host, it defined for itself what a systems check means, identified the corresponding commands, and proceeded to run it directly on my production host.</p>

<p>So this is an interesting, conversation based operator access experience but how does this approach actually make operator access more secure?</p>

<hr />

<p>To answer that question, I added an AI security agent (running off a <a href="https://ollama.com/library/llama2">llama2 model</a>) into the ssh-client MCP server which analyzes every incoming command to be run via the SSH connection, determines whether its safe or unsafe and for unsafe commands returns a message indicating that the command was rejected.</p>

<p><img src="/assets/img/raw/67d5771e-e315-49c5-a8b3-e18c3bebb77c_568x450.png" alt="" /></p>

<p>Note that you can configure how this security agent operates by specifying its SECURITY_POLICY in the <a href="https://github.com/jonnadul/mcpsshclient/blob/main/secagentconfig.json">secagentconfig.json</a>.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>{
  "ENABLE_SECAGENT": true,
  "SECURITY_POLICY": "\"ls\" is the only safe command, all other commands are unsafe"
}
</code></pre></div></div>

<p>Here is an instance of the AI security agent allowing me to run ls on my home directory.</p>

<p><img src="/assets/img/raw/468ecb6b-6a45-480a-a37b-334e287ecf67_1732x974.png" alt="" /></p>

<p>And here is an instance of the AI security agent not allowing me to create an empty text file.</p>

<p><img src="/assets/img/raw/1551dbc9-7d4c-48d6-9432-2c3dc1ecf0d6_1732x974.png" alt="" /></p>

<p>Some querks I observed is the llama2 model ran pretty slow possibly because I used a Standard D2ads v6 (2 vcpus, 8 GiB memory) on Azure. The security agent was also inconsistent in its designation of whether a command was safe vs unsafe and I think one way to address it in this demo is to prompt engineer the security policy statement and the command going to the llama2 model. However productizing this type of an approach for operator access governance will require adopting a security focused LLM model and agent like <a href="https://www.microsoft.com/en-us/security/business/ai-machine-learning/microsoft-security-copilot?msockid=033b0f5e3887618d35e41a3a39aa6098">Microsoft Copilot Security</a>, <a href="https://simbian.ai/">Simbinal AI</a>, etc to ensure the most accurate, consistent, and trustworthy behavior.</p>

<hr />

<p>I hope this served as a good case study for how these next generation of AI-based, Agentic systems have shifted the conversation and unlocked opportunities to go back and rethink traditional approaches! I’d love to get you feedback so please do drop a comment on either the blog post or my <a href="https://github.com/jonnadul/mcpsshclient/tree/main">Agentic MCP Server sshclient</a> project!</p>]]></content><author><name>Srujan Jonnadula</name></author><summary type="html"><![CDATA[Anthropic’s Model Context Protocol (MCP) standard has bridged a critical gap between large language models (LLMs) and applications. Enabling these models to operate with enhanced context and increased their applicability. The MCP standard has already proven wildly success fostering a rapidly expanding ecosystem and leading AI services like OpenAI, Microsoft Copilot, and Perplexity quickly embracing and supporting the standard. The release of this technology had me particularly revisiting a long-standing painpoint in cloud security with a fresh perspectives.]]></summary></entry><entry><title type="html">Cautions in the Open-Source AI-era</title><link href="https://fromthesimulation.blog/2025/03/19/open-source-in-the-ai-era.html" rel="alternate" type="text/html" title="Cautions in the Open-Source AI-era" /><published>2025-03-19T22:13:19-07:00</published><updated>2025-03-19T22:13:19-07:00</updated><id>https://fromthesimulation.blog/2025/03/19/open-source-in-the-ai-era</id><content type="html" xml:base="https://fromthesimulation.blog/2025/03/19/open-source-in-the-ai-era.html"><![CDATA[<p>When I read about industry leaders like <a href="https://www.businessinsider.com/meta-ai-yann-lecun-deepseek-open-source-openai-2025-1">Yann LeCun advocating the benefits of open-sourcing AI models</a> I feel conflicted. Open-source has been the driving force for innovation by fostering open collaboration and community engagement. However its operating model has been severally strained by our evolving world of threat actors and I fear for the consequences in the AI-era.</p>

<p>We had the infamous <a href="https://www.cisa.gov/news-events/news/apache-log4j-vulnerability-guidance">Apache Log4J remote execution CVE</a> a couple of years ago which impacted the entire internet, and almost everyone in the industry <a href="https://www.reddit.com/r/sysadmin/comments/reqc6f/log4j_0day_being_exploited_mega_thread_overview/?rdt=42128">spent their holidays doing patching and running security scans</a>. Then more recently a nation-state actor was found to have <a href="https://www.techrepublic.com/article/xz-backdoor-linux/">hidden a SSH backdoor in the foundational and popular XZ utils</a> on Linux. There was also an incident with the popular GitHub Actions <a href="https://www.cve.org/CVERecord?id=CVE-2025-30066">tj-actions/changed-file that allowed attackers to exfiltrate secrets</a>. That all combined with the <a href="https://www.theregister.com/2025/02/16/open_source_maintainers_state_of_open/">fatigue experience by open-source maintainers</a> further exacerbates the owes and eroded trust of the ecosystem.</p>

<hr />

<p>The proverbial cat is out of the bag however and we are ushered into the open-source AI-era. So maintainers and consumers of open-source AI models need to be responsible custodians of the trust and integrity of the ecosystem so we can safely collaborate and innovate together.</p>

<p>The open-source AI model maintainers should learn from the industry and:</p>

<ul>
  <li>Audit their models for security and code quality regularly; employ secure access control measures.</li>
  <li>Run vulnerability scanning (see <a href="https://www.darkreading.com/threat-intelligence/sleepy-pickle-exploit-subtly-poisons-ml-models">Sleepy Pickle</a>). They should also further protect the behavior integrity of their models from data poisoning attacks by.</li>
  <li>Ensuring encryption in transit (TLS) on their data ingestion pipelines.</li>
  <li>Embedding watermarks in the dataset to detect manipulation.</li>
  <li>Employ adversarial training to ensure models are less susceptible to prompt injections attacks.</li>
</ul>

<p>Most importantly, open-source AI models maintainers need to adopt a culture of trust and transparency both in the security practices they employ to ensure the integrity of the models the release and in timely disclosure of vulnerabilities.</p>

<p>The consumers of open-source AI models should also learn from the industry on supply-chain protection best practices and:</p>

<ul>
  <li>Audit and track their consumption of OSS/AI and dependencies.</li>
  <li>Employ vulnerability scanning.</li>
  <li>Access control best practices.</li>
  <li>Ensure deployment integrity of these models into their production environment.</li>
</ul>

<p>Consumers should also ingest multiple AI models to further spread the risk of being impacted by a single vulnerability. And lastly ensure they have a robust CI/CD and patching strategy to ensure they can quickly act to patch vulnerabilities.</p>

<p>Finally the end customers of these open-source AI models and services need to exercise extreme caution and ensure they are not sharing personal or work-related information, maintaining awareness of the context behind certain models (especially ones originating from China), and being vigilant in staying up-to-date on patches.</p>

<p>The open-source ecosystem is a bit of a burning building at the moment, and introducing AI-models into the mix feels like adding more fuel. However I’m cautiously optimistic.</p>]]></content><author><name>Srujan Jonnadula</name></author><summary type="html"><![CDATA[When I read about industry leaders like Yann LeCun advocating the benefits of open-sourcing AI models I feel conflicted. Open-source has been the driving force for innovation by fostering open collaboration and community engagement. However its operating model has been severally strained by our evolving world of threat actors and I fear for the consequences in the AI-era.]]></summary></entry><entry><title type="html">Solving a Cryptographic Mystery</title><link href="https://fromthesimulation.blog/2024/01/21/brute-forcing-ecdsa-seeds-using-openai.html" rel="alternate" type="text/html" title="Solving a Cryptographic Mystery" /><published>2024-01-21T00:17:36-08:00</published><updated>2024-01-21T00:17:36-08:00</updated><id>https://fromthesimulation.blog/2024/01/21/brute-forcing-ecdsa-seeds-using-openai</id><content type="html" xml:base="https://fromthesimulation.blog/2024/01/21/brute-forcing-ecdsa-seeds-using-openai.html"><![CDATA[<p>A few months back I came across this <a href="https://saweis.net/posts/nist-curve-seed-origins.html">blog post</a> by <a href="https://infosec.exchange/@sweis">Steve Weis</a> which goes as follows.</p>

<p>Since the inception of <a href="https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm">ECDSA</a> there have been controversies and debate especially around the seed values used at its foundation. These seed values were chosen by Jerry Solinas, a NSA employee collaborating with the authors of the ECDSA RFC at the time, and it was unearthed that he didn’t choose this at random and instead used a phrase. The phrase was allegedly just a <a href="https://en.wikipedia.org/wiki/SHA-1">SHA-1</a> hash of the phrase “Jerry deserves a raise…”. Jerry has since forgotten the exact phrase and had even attempted to uncover it himself without success. Unfortunately Jerry died in early 2023.</p>

<p>So the question remains, what was the original phrase? Even prominent cryptographers and security folks have asked and even <a href="https://words.filippo.io/dispatches/seeds-bounty/">set cash bounties</a>! I felt I had to give it a shot.</p>

<hr />

<h2 id="the-approach">The Approach</h2>

<p>According to the blog post, Jerry simply SHA-1 hashed an English sentence along with a discrete number of digits to generate the ECDSA seed values. Something like:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>seed = SHA-1("Jerry and Bob need raises123")
</code></pre></div></div>

<p>Since the format is pretty simple, and most of the value is dictionary words, I figure it’ll be a small enough search space for me to run a <a href="https://en.wikipedia.org/wiki/Brute-force_attack">brute-force</a> and try all possible ways to say the phrase and add incrementing permutations of char values and SHA-1 hash it to see it’ll match any of the ECDSA seed values.</p>

<p>1.</p>

<p>Using OpenAI seems like the easiest way find out all the ways to say “Jerry and Bob need raises”.</p>

<p>2.</p>

<p>For the additional values, I’ll recursively generate all permutations of chars from the full <a href="https://www.asciitable.com">ASCII values</a> and attach it both to the front, back, and front/back of the phrase.</p>

<p>3.</p>

<p>Even if the search space is truly this narrow it’ll take forever to run through this brute-force in series. So I’ll spawn threads for each of the phrases that’ll run through all permutations, to make the effort multithreaded.</p>

<p>Here is my <a href="https://gist.github.com/jonnadul/ad4eab0bac13cf44cb42e401045e1dac">brute force golang application</a>.</p>

<hr />

<h2 id="the-results">The Results</h2>

<p>I ran the above application for 48 hours on a 1 OCPU E2 VM in my free tier account on Oracle Cloud. And unfortunately I was unable to uncover any of the ECDSA seeds. But I made a few interesting observations.</p>

<p>After the first 200 or so the phrases being returned by OpenAI were getting longer and wordier making their likeliness to be the original phrase less plausible. Placing restrictions on the phrases returned, like asking OpenAI to reducing word count, only caused it to give-up earlier. The strategy for the additional values needs to be further thought out like increasing the max length to beyond 3 and trying attempts where I sprinkle it through the phrase than just pre-pending/post-pending. Also obviously I’ll need a beefier hardware, the 1 OCPU was being nearly fully utilized at almost 98% for the entire 48 hours!</p>

<p>At this point my initial approach has hit a brick wall. But I have some ideas on how to iterate on this approach further, so stay tuned!</p>]]></content><author><name>Srujan Jonnadula</name></author><summary type="html"><![CDATA[A few months back I came across this blog post by Steve Weis which goes as follows.]]></summary></entry><entry><title type="html">Journey to the center of the world</title><link href="https://fromthesimulation.blog/2015/12/12/journey-to-the-center-of-the-world.html" rel="alternate" type="text/html" title="Journey to the center of the world" /><published>2015-12-12T04:00:00-08:00</published><updated>2015-12-12T04:00:00-08:00</updated><id>https://fromthesimulation.blog/2015/12/12/journey-to-the-center-of-the-world</id><content type="html" xml:base="https://fromthesimulation.blog/2015/12/12/journey-to-the-center-of-the-world.html"><![CDATA[<p><img src="/assets/img/raw/1_r5oLQGcyTjhHuCybCzXMBA.jpeg" alt="" /></p>

<p><em>Here is a collection of photos, and experiences, of what started off as an impulsive plan to escape but turned out to be one of the most amazing experiences of our lives. From the tops of the Andes mountain ranges to the basin of the Amazon rainforest, Ecuador truly is a beautiful country only made more beautiful by the warmth of its people.</em></p>

<p><em>Here are a few pictures I capture on our 4-hour journey through the Andes mountain range from Quito, the capitol city of Ecuador, to Tena, where we will be spending the next week.</em></p>

<p><img src="/assets/img/raw/1_TPoKaEUsugcWbZWrtmZg0Q.jpeg" alt="" /></p>

<p><em>This is Pichincha, an active volcano near Quito.</em></p>

<p><img src="/assets/img/raw/1_M03Qaj-hgLUp7IHgYNCLaw.jpeg" alt="" /></p>

<p><em>A departing picture of Quito valley, which sits 10,000 ft above sea level making it the highest capitol city in the world.</em></p>

<p><img src="/assets/img/raw/1_NKcUpDIHC415uaxMfZC1zQ.jpeg" alt="" /></p>

<p><em>These waterfalls are called The Three Marys.</em></p>

<p><img src="/assets/img/raw/1_1NLNpTSaV0bItvKIa0OZmQ.jpeg" alt="" /></p>

<p><em>Some random creepy clowns promoting recycling by a gas station.</em></p>

<p><em>Our accommodations were at *<a href="http://tomas-lodge.com/">*El Establo De Tomas*</a></em>, a small colony of log cabins off the Lupi river just outside of Tena.*</p>

<p><img src="/assets/img/raw/1_czBnKlrv5F4F0itv1yDpSQ.jpeg" alt="" /></p>

<p><em>View of the Lupi river from the lodge.</em></p>

<p><img src="/assets/img/raw/1_eGY_OtBVfPp2BK1ezoTm9Q.jpeg" alt="" /></p>

<p><img src="/assets/img/raw/1_GQv63JgRuJgslS91TizH8w.jpeg" alt="" /></p>

<p><em>One of log cabins in our lodge, I think this was the one where we found the snake.</em></p>

<p><img src="/assets/img/raw/1_blTi6zrvgx8_IWyoWJJV5g.jpeg" alt="" /></p>

<p><em>This is one of the many parrots and macaws at our lodge.</em></p>

<p><img src="/assets/img/raw/1_IIhs0Jo328bJlXpOQlcIJw.jpeg" alt="" /></p>

<p><em>I took this picture on our first evening in Tena, after we got our room assignments. As I took this picture, a bat flew out of the roof swooping every which way! Only to disappear whenever we ran out to get help. The story of the bat in our room quickly spread throughout our group, half met with disbelief and half met with reassurances that at least we don’t have to worry about insects in our room. All of which turned out to be a great story to tell our friends and family.</em></p>

<p><em>From our lodge in Tena, we spent the next week going to different remote locations in the Napo region where we set up Timmy Clinics, and received upwards of a hundred patients.</em></p>

<p><img src="/assets/img/raw/1_vM8N647opS630-RXzqy8EQ.jpeg" alt="" /></p>

<p><em>On our way to one of the locations, we had to cross the Napo river by boat. But the combination of the boat’s inability to properly handle our tour bus and poor road conditions managed to put a slight dent in our arrival time.</em></p>

<p><img src="/assets/img/raw/1_5HHv2rCp_l366O7GH6PCvw.jpeg" alt="" /></p>

<p><em>My Fiancee and the rest of the vitals gang!</em></p>

<p><img src="/assets/img/raw/1_UaKTapnJpHCAVWH9_f9n7g.jpeg" alt="" /></p>

<p><em>One of the locations we went to was inaccessible via our tourbus. So we took pickup trucks there instead.</em></p>

<p><img src="/assets/img/raw/1_ul6hGjz4VN4g15Vce4qgrw.jpeg" alt="" /></p>

<p><em>One of the stations we maintained was the Fluoride stations, where we would teach kids how to brush their teeth and maintain good hygiene. But we ended up just playing with them.</em></p>

<p><img src="/assets/img/raw/1_Eh0pSlkMpoGxau5KPSk_0A.jpeg" alt="" /></p>

<p><em>Here is Kathleen, is one of the many medical professionals we provided assistance to.</em></p>

<p><img src="/assets/img/raw/1_7dOjLy9l2ZCpf6Ll12lOCg.jpeg" alt="" /></p>

<p><em>Here is Jessica, a study-abroad student in Quito, who joined us to help with translation.</em></p>

<p><img src="/assets/img/raw/1_a5jno3Hxa3xLPwDVxKpQaA.jpeg" alt="" /></p>

<p><em>This kids name is Hamilton, easily one of the favorites!</em></p>

<p><img src="/assets/img/raw/1_vlW9njBrk2MCTs8OyPtQGQ.jpeg" alt="" /></p>

<p><em>Here is Mike who, along with his family, has come to this area every year via Timmy for many years.</em></p>

<p><img src="/assets/img/raw/1_SJhhgG-XXb3-La82vZ61oA.jpeg" alt="" /></p>

<p><em>On our last day we visited a regional hospital in Archidona, which is still many miles away from the regions we visited, to get an understand of the available established medical facilities.</em></p>

<p><img src="/assets/img/raw/1_rzVu9Y2R4-DPVVst1ZZGgw.jpeg" alt="" /></p>

<p><em>Though the days were long and filled with hard work, there really was a deep gratification in seeing these families getting the medical attention they need and through it all we found ourselves forming deep connections with the locals as well as ourselves in the group, bonds that are still resonating with us to this day.</em></p>]]></content><author><name>Srujan Jonnadula</name></author><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Charting the Developer World</title><link href="https://fromthesimulation.blog/2014/09/03/charting-the-developer-world.html" rel="alternate" type="text/html" title="Charting the Developer World" /><published>2014-09-03T05:00:00-07:00</published><updated>2014-09-03T05:00:00-07:00</updated><id>https://fromthesimulation.blog/2014/09/03/charting-the-developer-world</id><content type="html" xml:base="https://fromthesimulation.blog/2014/09/03/charting-the-developer-world.html"><![CDATA[<p><img src="/assets/img/raw/1_EBspffrBD4pXdcxg53HpNg.png" alt="" /></p>

<p><em>A simple project to map the social aspect of Github.</em></p>

<p><a href="https://www.github.com">Github</a> recently hosted a <a href="https://github.com/blog/1864-third-annual-github-data-challenge">data challenge</a>, the premise of which was to use their exposed <a href="https://developer.github.com/v3/">APIs</a> to do something interesting. At first I was just curious in the level of access they exposed, which btw is very expansive, but then I stumbled across an idea. I was interesting in capturing and visualizing the social interconnections which binded Github in a very fundamental way.</p>

<h3 id="overview">Overview</h3>

<h4 id="functionality">Functionality</h4>

<p><img src="/assets/img/raw/1_a4uAo54cvV2XsrDkydHNXQ.png" alt="" /></p>

<p><em>Screencap of Github-map</em></p>

<p>The application basically takes in a Github username, queries all public facing repositories of that user, queries all the watchers of each repository, and generates a node-link tree mapping these relationships.</p>

<h4 id="software-layout">Software Layout</h4>

<p><img src="/assets/img/raw/1_1UYj3INbdr7IluWYAmMvKg.png" alt="" /></p>

<p>The front-end is drive by <a href="https://angularjs.org/">AngularJS</a>, a very popular MVC framework, with visualizations being handled by <a href="http://d3js.org/">D</a>3. The back-end is driven by <a href="http://nodejs.org/">NodeJS</a>, which handles queries to Github APIs, using <a href="https://github.com/mikedeboer/node-github">node-github</a>. Query results are handled as JSON objects and exchanged to the front-end via REST, <a href="http://scotch.io/tutorials/javascript/build-a-restful-api-using-node-and-express-4">see</a>.</p>

<h3 id="github-api-query">Github API Query</h3>

<p>Using <a href="https://github.com/mikedeboer/node-github">node-github</a>, which wraps most of the raw APIs into nicely organized functions, for the back-end code querying code was relatively simple. Due to the event driven nature, I ended up having to use <a href="https://www.promisejs.org/">promises</a> (and some hacky-coding lol) to maintain a certain level of procedural flow.</p>

<ul>
  <li><strong>github.repo.getFromUser()</strong>: Returns all repositories for a github username.</li>
  <li><strong>github.repos.getWatchers()</strong>: Returns all watchers for a github repository.
*See, *<a href="https://github.com/jonnadul/github-map/blob/master/server.js"><em>server.js</em></a>.</li>
</ul>

<p>NOTE: As you read on to the next section, the data to that is to be visualized needed to be in a certain JSON format. You’ll notice that the back-end code is aware of this format and maintains this structure as it handles responses from Github queries.</p>

<h3 id="data-visualization">Data Visualization</h3>

<p>Since I was using <a href="https://angularjs.org/">AngularJS</a> as the front-end solution, it only made sense to incorporate the D3 engine within that framework as well. We do this by writing a custom <a href="https://docs.angularjs.org/guide/directive">directive</a>.</p>

<h4 id="dependency-injection">Dependency Injection</h4>

<p>Before going about doing this, we want to setup the actual D3 dependency so it can be injected into the custom directive. This will be residing within an angular <a href="https://docs.angularjs.org/guide/providers">factory</a>.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>angular.module('d3', [])
.factory('d3Service', ['$document', '$window', '$q', '$rootScope',
	function($document, $window, $q, $rootScope) {
 		var d = $q.defer(),
 	d3service = {
 		d3: function() { return d.promise; }
 	};
 	function onScriptLoad() {
 		// Load client in the browser
 		$rootScope.$apply(function() { d.resolve($window.d3); });
 	}
 	var scriptTag = $document[0].createElement('script');
 	scriptTag.type = 'text/javascript'; 
 	scriptTag.async = true;
 	scriptTag.src = 'http://d3js.org/d3.v3.min.js';
 	scriptTag.onreadystatechange = function () {
 		if (this.readyState == 'complete') onScriptLoad();
 	}
 	scriptTag.onload = onScriptLoad;
 
 	var s = $document[0].getElementsByTagName('body')[0];
 	s.appendChild(scriptTag);
 
 	return d3service;
}]);
</code></pre></div></div>

<h4 id="d3-custom-directive">D3 Custom Directive</h4>

<p>Now we are ready to write the D3 custom directive.</p>

<p>Below is a template for how the D3 directive could look like, with the core D3 code residing within the $timeout() function. The rest of the wrapping code is intended to handle the changes in data (and the viewing environment) that affect the rendering.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ghmapApp.directive('d3Bars', ['$window', '$timeout', 'd3Service',
	function($window, $timeout, d3Service) {
		return {
 			restrict: 'A',
 			scope: {
 		data: '=',
 		label: '@',
 		onClick: '&amp;'
 		},
	link: function(scope, ele, attrs) {
		d3Service.d3().then(function(d3) {
 
 	var renderTimeout;
	var svg = d3.select(ele[0])
		.append("svg");
 
 	$window.onresize = function() {
 		scope.$apply();
 	};
 
 	scope.$watch(function() {
 		return angular.element($window)[0].innerWidth;
 	}, function() {
 		scope.render(scope.data);
 	});
 
 	scope.$watch('data', function(newData) {
 		scope.render(newData);
 	}, true);
 
 	scope.render = function(data) {
 		svg.selectAll('*').remove();
 
 		if (!data) return;
			if (renderTimeout) clearTimeout(renderTimeout);
	 
			renderTimeout = $timeout(function() {
 				/*Write your D3.js code here*/
 	};
	});
	}}
}]);
</code></pre></div></div>

<p>The benefit to this template is that it added a dynamic element to the visualization rendering process. For a more in-depth explanation check out this <a href="http://www.ng-newsletter.com/posts/d3-on-angular.html">post</a>. One important note is to set the overarching <em>d3.select(ele[0])</em>, this will keep your animation within the bounds of the DOM element from which the directive is called.</p>

<p>Now its as simple as adding the following line into your *.html page.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;div d3-bars align="center" data="data"&gt;&lt;/div&gt;
</code></pre></div></div>

<p>For my app I used the D3 and CSS code snippets from <a href="http://bl.ocks.org/mbostock/4063550">Radial Reingold–Tilford Tree</a>, by <a href="http://bl.ocks.org/mbostock">mbostock</a>, as my core D3 code to generated my node-link tree visual.</p>

<p><em>See, *<a href="https://github.com/jonnadul/github-map/blob/master/public/core.js">*core.js*</a></em> and <em><a href="https://github.com/jonnadul/github-map/blob/master/public/index.html">*index.html*</a></em>.*</p>

<p>NOTE: Check out following <a href="https://leanpub.com/d3angularjs">book</a>, it provides deep insight into the real power of utilizing D3 and Angular to make super lean and dynamic web apps.</p>

<p>And that’s its! Outside of a few interesting corner cases, most of the software pieces feel into place very nicely! Please check out my project <a href="https://github.com/jonnadul/github-map">here</a>, and constructive feedback is always appreciated ☺.</p>]]></content><author><name>Srujan Jonnadula</name></author><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Angular JS + Firebase</title><link href="https://fromthesimulation.blog/2014/03/28/angular-js-firebase.html" rel="alternate" type="text/html" title="Angular JS + Firebase" /><published>2014-03-28T05:00:00-07:00</published><updated>2014-03-28T05:00:00-07:00</updated><id>https://fromthesimulation.blog/2014/03/28/angular-js-firebase</id><content type="html" xml:base="https://fromthesimulation.blog/2014/03/28/angular-js-firebase.html"><![CDATA[<p><img src="/assets/img/raw/1_u9gEfWbI8N4uUBeuImKzxg.png" alt="" /></p>

<p>I understand that there are tons of frameworks and back-end solutions out there catering to the multitude of types of web apps but my criteria when it came to picking the best package was rapid prototype-ability and an easiest learning curve (I am actually new to web app dev ☺). I have found both <a href="https://www.firebase.com/">Firebase</a> and <a href="http://angularjs.org/">Angular JS</a>, btw I highly recommend the fundamentals course by <a href="http://pluralsight.com/training/Courses/TableOfContents/angularjs-fundamentals">plural sight</a>, to be well documented and fairly intuitive to learn and use. Here are some example of historically complex features made simple by AngularFire (Angular JS + Firebase), check out Firebase’s <a href="https://www.firebase.com/quickstart/angularjs.html">official</a> support for this package.</p>

<p>Before you start be sure to have a Firebase account setup, you can setup a free <em>Hacker Plan</em> account which is limiting in terms of resources but perfect for rapid prototyping.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>var myApp = angular.module(‘myApp’, [‘firebase’]);
</code></pre></div></div>

<p>Also include the following module into your app.js.</p>

<h4 id="user-signup-and-login">User Signup and Login</h4>

<p>This example goes through and demonstrates the Email &amp; Password method of user signup and login, note that Firebase supports login via Facebook and other platforms as well.</p>

<p><img src="/assets/img/raw/1_C0eZoNjjAIUEq8UJNJhLnA.png" alt="" /></p>

<p>Within Firebase be sure to go to <em>Dashboard-&gt;Simple Login-&gt;Email &amp; Password</em> and click the <strong>Enabled</strong> radio button.</p>

<p>Now within your controller you will need to include the following code snippet.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>var ref = new Firebase(“https://xxYYzz.firebaseIO.com");
</code></pre></div></div>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>var auth = new FirebaseSimpleLogin(ref, function(error, user) {
  if (error) {
    // an error occured while attempting login
    console.log(error);
  } else if (user) {
    // user authenticated with Firebase
    console.log(user.id + ', ' + user.provider);
  } else {
    // user is logged out
  }
});
</code></pre></div></div>

<p><em>Note that <strong>*https://xxYYzz.firebaseIO.com</strong></em> will need to be replaced with url to your Firebase instance.*</p>

<p>The most important variable above is the <em>auth *variable, which you can use for session management. Notice that the second function parameter within *FirebaseSimpleLogin()</em> contains conditional statements which serve as your callback for the cases where; an error occurred while attempting login, user successfully authenticated with Firebase, and user is logged out.</p>

<h4 id="signup">Signup</h4>

<p>Now that you have the *auth *variable, the client side code to create a new user is as easy as follows.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>auth.createUser(newUser.emailaddress, newUser.password,
  function(error, user) {
    if (!error) {
      console.log(user.id + ', ' + user.provider);
    }
  });
}
</code></pre></div></div>

<p>In this example, <em>newUser</em> is a model with an email address and password that is being passed in from the view. Notice that you can check if the <em>createUser()</em> was successful via the <em>error</em> variable.</p>

<p><img src="/assets/img/raw/1_ZYejC0RpTgflP6rE-3BI0Q.png" alt="" /></p>

<p>You can also verify that a user was created successfully by simple going back into *Dashboard-&gt;Simple Login-&gt;Email &amp; Password *in your Firebase account and see that newly created record.</p>

<h4 id="login">Login</h4>

<p>Using the same *auth *variable, you can perform a login operation as well.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>auth.login(‘password’, {
  email: user.emailaddress,
  password: user.password
})
</code></pre></div></div>

<p>You can also persist a login session, up to 30 days, by setting the following.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rememberMe: true
</code></pre></div></div>

<p>And thats it! With very minimal client side, controller js code you have implemented user signup and login capability. You can read more about Firebase’s simple login <a href="https://www.firebase.com/docs/security/simple-login-email-password.html">here</a>.</p>

<p>For additional features and tighter bindings between AngularJS and Firebase checkout the following <a href="https://www.firebase.com/quickstart/angularjs.html">link</a>.</p>]]></content><author><name>Srujan Jonnadula</name></author><summary type="html"><![CDATA[]]></summary></entry></feed>