<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: StareBrain</title>
    <description>The latest articles on DEV Community by StareBrain (@starebrain).</description>
    <link>https://dev.to/starebrain</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4120144%2F52c81a31-4d01-4ae0-ac7c-92f5e597d857.png</url>
      <title>DEV Community: StareBrain</title>
      <link>https://dev.to/starebrain</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/starebrain"/>
    <language>en</language>
    <item>
      <title>The confirmation your app shows isn't the confirmation that matters</title>
      <dc:creator>StareBrain</dc:creator>
      <pubDate>Fri, 11 Sep 2026 03:56:36 +0000</pubDate>
      <link>https://dev.to/starebrain/the-confirmation-your-app-shows-isnt-the-confirmation-that-matters-57mo</link>
      <guid>https://dev.to/starebrain/the-confirmation-your-app-shows-isnt-the-confirmation-that-matters-57mo</guid>
      <description>&lt;p&gt;If you're building anything that lets an AI agent act on a user's behalf — send a message, book something, control a device — there's a failure mode that's easy to miss until it bites you: the gap between "permission was granted" and "permission is still valid right now."&lt;/p&gt;

&lt;p&gt;The scenario&lt;/p&gt;

&lt;p&gt;Imagine this timeline:&lt;/p&gt;

&lt;p&gt;T+0:00 — An agent has permission to perform an action, and that authority is valid.&lt;br&gt;
T+0:04 — The authority is revoked, or the world changes underneath it (a contact's number updates, a calendar slot fills, a setting reverts).&lt;br&gt;
T+0:05 — The agent still has the technical capability to execute.&lt;br&gt;
T+0:06 — A downstream system records the action as complete.&lt;/p&gt;

&lt;p&gt;The agent had permission. Was it still authorized at the moment it actually mattered? Those are different questions, and most systems don't distinguish them.&lt;/p&gt;

&lt;p&gt;Why "blocked" often lies&lt;/p&gt;

&lt;p&gt;Say you catch the problem and try to stop the action after authority changes. If the request has already been dispatched to an external system — an SMS provider, a calendar API — simply flipping your own app's state to "blocked" doesn't prove anything happened, or didn't. You're guessing, dressed up as a system that checked.&lt;/p&gt;

&lt;p&gt;This showed up for me building a confirm-before-execute layer for phone commands. A stale result from an earlier attempt rendered as "executed" right after a new attempt correctly denied the same action. The denial was truthful about the decision. It was silent about the actual state of the world.&lt;/p&gt;

&lt;p&gt;Three states, not two&lt;/p&gt;

&lt;p&gt;Most systems track two outcomes: executed, or blocked. That's not enough. The honest model needs three:&lt;/p&gt;

&lt;p&gt;EXECUTED — observed evidence the intended side effect actually occurred.&lt;br&gt;
DENIED_CONFIRMED — denied, and verified the action never crossed the execution boundary.&lt;br&gt;
DENIED_UNRESOLVED — denial was intended, but available evidence can't independently establish whether a downstream side effect occurred anyway.&lt;/p&gt;

&lt;p&gt;That third state is the one most systems don't have a slot for at all. Without it, uncertainty silently gets rounded up to a confident "blocked" — which is worse than an honest "I don't know," because it actively points you away from checking.&lt;/p&gt;

&lt;p&gt;The fix that keeps showing up&lt;/p&gt;

&lt;p&gt;Talking this through with people building completely different systems — WordPress admin tools, AI ops platforms, agent authorization layers — the same pattern kept surfacing independently:&lt;/p&gt;

&lt;p&gt;Never trust an earlier authorization check. Re-verify right before execution, not when the action was first requested.&lt;br&gt;
Bind confirmation to exact parameters. A dry run returns a short-lived token tied to the specific values (recipient, time, amount). Confirm has to present that token, byte-identical, or it's treated as a new plan requiring fresh approval — not a rubber-stamp of the old one.&lt;br&gt;
Once dispatched externally, "blocked" isn't a real status anymore. Only a provider receipt or webhook can close the loop. Until then, the honest label is "submitted, unresolved" — not "blocked," and definitely not "executed."&lt;br&gt;
What this changes practically&lt;/p&gt;

&lt;p&gt;For a phone-command interface, the gap between showing someone a plan and firing it is usually seconds — but "short" isn't "zero." A dry run now returns a hash of everything the action depends on. Confirm has to match that hash exactly, or it's rejected as stale and requires a fresh confirmation. Cheap to build, and it closes a real gap that used to be invisible.&lt;/p&gt;

&lt;p&gt;The broader lesson: if your system can't tell "we decided not to do this" apart from "we don't know what happened," you don't have a permission system — you have a permission system's confident-sounding guess.&lt;/p&gt;

&lt;p&gt;Building StareBrain — natural language commands for Android, with exactly this confirmation model at its core. Currently pre-launch: starebrain.vercel.app&lt;/p&gt;

</description>
      <category>ai</category>
      <category>android</category>
      <category>kotlin</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
