<?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: Yaima Valdivia</title>
    <description>The latest articles on DEV Community by Yaima Valdivia (@yaimavaldivia).</description>
    <link>https://dev.to/yaimavaldivia</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%2F3974412%2F06421353-6c35-4b4d-895f-a4d407d81ae0.jpg</url>
      <title>DEV Community: Yaima Valdivia</title>
      <link>https://dev.to/yaimavaldivia</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yaimavaldivia"/>
    <language>en</language>
    <item>
      <title>A denial with no reason is a bug</title>
      <dc:creator>Yaima Valdivia</dc:creator>
      <pubDate>Sat, 13 Jun 2026 02:42:18 +0000</pubDate>
      <link>https://dev.to/yaimavaldivia/a-denial-with-no-reason-is-a-bug-c1k</link>
      <guid>https://dev.to/yaimavaldivia/a-denial-with-no-reason-is-a-bug-c1k</guid>
      <description>&lt;p&gt;Fail-closed is the correct default for an authorization system. If the component that decides "should this action happen" can't reach the component that knows the policy, the safe answer is no. AgentTrust ID is built that way on purpose: when in doubt, deny.&lt;/p&gt;

&lt;p&gt;But fail-closed has a failure mode that is easy to miss, and it is worth naming: &lt;strong&gt;a denial that doesn't say why.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Two systems that both "deny"
&lt;/h2&gt;

&lt;p&gt;Imagine two authorization systems. Both deny a write action. The first returns:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;denied: action 'email:send' is read-only in this session; elevation required&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The second returns:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;denied&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;From the caller's seat they look similar. The action didn't happen, the system failed closed, no harm done. But operationally they are worlds apart. The first is a working system telling you something true. The second is a black box, and a black box that always says "no" is indistinguishable from a system that is &lt;strong&gt;completely broken&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That is the trap. A component that is supposed to make nuanced allow/deny decisions, but is actually misconfigured and rejecting everything upstream, looks exactly like a strict policy doing its job, as long as the denials carry no reason. Your read paths keep working. Your health checks stay green. And the entire decision layer underneath could be returning a blank "no" to every consequential action without anyone noticing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters more for agents
&lt;/h2&gt;

&lt;p&gt;For an agent platform the cost is higher than a confusing error message.&lt;/p&gt;

&lt;p&gt;The whole point of per-action authorization is the &lt;strong&gt;reason&lt;/strong&gt;. "This was denied because the session is read-only and no elevation was approved" is the thing a developer debugs against, the thing a security reviewer reads in the audit trail, and the thing that lets you tell a customer &lt;em&gt;why&lt;/em&gt; their agent couldn't do something. Strip the reason out, and you've quietly broken the audit story, because an audit entry that records "denied, no reason" is noise.&lt;/p&gt;

&lt;p&gt;So we treat it as a hard rule: &lt;strong&gt;every decision carries its reason and the tier that made it.&lt;/strong&gt; Allow or deny, &lt;a href="https://dev.to/blog/three-tiers-routed-by-risk"&gt;Fast Guard, Spot Guard, or Deep Guard&lt;/a&gt;, the response says which path ran and why. A blank denial is a bug, and we surface it as one (&lt;code&gt;guardian returned HTTP 401&lt;/code&gt;, &lt;code&gt;empty decision&lt;/code&gt;, and so on) rather than letting it masquerade as a decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  You only know this works if you test the risky path
&lt;/h2&gt;

&lt;p&gt;There is an uncomfortable corollary. The happy path will not tell you any of this.&lt;/p&gt;

&lt;p&gt;If your tests only check that a read is allowed, you are exercising the cheapest, safest branch in the whole system, the one most likely to work even when everything behind it is broken. The denial path, the escalation path, the "this is a mutation so it has to go through real policy" path: those are where the bugs that matter live, because those are the branches that actually depend on every downstream component being wired correctly.&lt;/p&gt;

&lt;p&gt;So the test that earns its keep is the one that drives the risky action end to end and asserts three things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the &lt;strong&gt;decision&lt;/strong&gt; is what you expect,&lt;/li&gt;
&lt;li&gt;the response carries a &lt;strong&gt;reason and a tier&lt;/strong&gt;, not a blank "no", and&lt;/li&gt;
&lt;li&gt;an &lt;strong&gt;audit record&lt;/strong&gt; actually landed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A green suite that never drives a mutation, never asserts a reason, and never checks the audit write can sit on top of a decision layer that is doing nothing at all. The feature can look shipped and be hollow.&lt;/p&gt;

&lt;h2&gt;
  
  
  The principle
&lt;/h2&gt;

&lt;p&gt;Deny by default. Always. But make the system &lt;strong&gt;explain itself every single time&lt;/strong&gt;, treat a reasonless denial as a defect rather than a decision, and write the tests that drive the dangerous path so you find out when it stops working, before your users do.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>security</category>
      <category>softwareengineering</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>AgentTrust ID is live</title>
      <dc:creator>Yaima Valdivia</dc:creator>
      <pubDate>Mon, 08 Jun 2026 15:24:05 +0000</pubDate>
      <link>https://dev.to/yaimavaldivia/agenttrust-id-is-live-agn</link>
      <guid>https://dev.to/yaimavaldivia/agenttrust-id-is-live-agn</guid>
      <description>&lt;p&gt;This weekend, &lt;a href="https://agenttrust.id" rel="noopener noreferrer"&gt;AgentTrust ID&lt;/a&gt; went live in production. As of today, all five SDKs are published:&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;agenttrustid
npm &lt;span class="nb"&gt;install&lt;/span&gt; @agenttrustid/sdkgo get github.com/agenttrustid/sdk/go
cargo add agenttrustid
&lt;span class="c"&gt;# Maven / Gradle&lt;/span&gt;
&lt;span class="c"&gt;# id.agenttrust:agenttrustid:0.3.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The SDKs are open source under Apache 2.0 at &lt;a href="https://github.com/agenttrustid/sdk" rel="noopener noreferrer"&gt;github.com/agenttrustid/sdk&lt;/a&gt;. The hosted platform is running at &lt;a href="https://app.agenttrust.id" rel="noopener noreferrer"&gt;app.agenttrust.id&lt;/a&gt; in a controlled beta.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I built this
&lt;/h2&gt;

&lt;p&gt;AI agents broke the assumptions that machine-to-machine security was built on. An API key answers one question: who is calling. It asks it once, at the door. An agent decides its next action at runtime, from context nobody wrote by hand. The same agent that summarized a document a second ago might now try to email it, delete it, or chain a task to another agent. A credential that only proves identity has no opinion about any of that.&lt;/p&gt;

&lt;p&gt;Agents need a decision at the &lt;strong&gt;action boundary&lt;/strong&gt;: &lt;em&gt;should this specific action happen, right now, on whose behalf&lt;/em&gt;. Answered at runtime, every time, with an audit trail and a kill switch.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's running
&lt;/h2&gt;

&lt;p&gt;Everything below is live in production today, not a roadmap:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Per-action authorization.&lt;/strong&gt; Every consequential action passes a pre-flight check. The &lt;a href="https://agenttrust.id/blog/three-tiers-routed-by-risk" rel="noopener noreferrer"&gt;Guardian pipeline&lt;/a&gt; routes each action by risk: deterministic rule checks for the common path, a policy engine for mutations, and AI-backed review for destructive operations. Fail-closed where it counts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Opaque, instantly revocable tokens.&lt;/strong&gt; Credentials are &lt;code&gt;at_&lt;/code&gt; references with &lt;a href="https://agenttrust.id/blog/revoke-in-seconds-the-agent-kill-switch" rel="noopener noreferrer"&gt;no standing authority of their own&lt;/a&gt;. The server decides on every use, so revocation is one call, effective immediately.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scoped delegation.&lt;/strong&gt; When one agent hands work to another, the grant &lt;a href="https://agenttrust.id/blog/scoped-delegation-narrow-not-copy" rel="noopener noreferrer"&gt;narrows instead of copying&lt;/a&gt;: subset scopes, independent TTLs, independently revocable, bounded chain depth.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read-only sessions with time-boxed elevation.&lt;/strong&gt; Sessions &lt;a href="https://agenttrust.id/blog/read-only-by-default-sessions-and-elevation" rel="noopener noreferrer"&gt;start safe&lt;/a&gt; and rise only on approval, for a bounded window, then revert on their own.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One model across surfaces.&lt;/strong&gt; MCP tools, agent-to-agent calls, and direct API integrations all route through the same decision, not three security stories.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where it stands
&lt;/h2&gt;

&lt;p&gt;The platform is in an invite-only beta while I onboard design partners. If runtime authorization for agents is a problem you have right now, &lt;a href="https://agenttrust.id/#contact" rel="noopener noreferrer"&gt;request access&lt;/a&gt; and tell me about your setup.&lt;/p&gt;

&lt;p&gt;If you'd rather kick the tires first: the &lt;a href="https://github.com/agenttrustid/sdk" rel="noopener noreferrer"&gt;SDKs&lt;/a&gt; are open, the &lt;a href="https://agenttrust.id/docs" rel="noopener noreferrer"&gt;docs&lt;/a&gt; are public, including an honest &lt;a href="https://agenttrust.id/docs/whats-supported" rel="noopener noreferrer"&gt;what's supported&lt;/a&gt; page that says what this does &lt;em&gt;not&lt;/em&gt; do yet.&lt;/p&gt;

&lt;p&gt;Agents are already acting at machine speed. The authorization layer should keep up. Now it does.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>opensource</category>
      <category>python</category>
    </item>
  </channel>
</rss>
