Why I'm Rethinking How We Handle Approvals in AI-Assisted Systems
Admin User
Author
I had a bug in production last month that kept me awake. A financial reconciliation screen showed an AI-suggested refund batch for 12 orders totaling $430. Our team lead approved it. By the time the system executed the action 90 seconds later, new orders had rolled in. The approval went through for 19 orders worth $760. Nobody noticed until the next morning when the CFO asked why we'd issued double the refunds we'd authorized.
That one incident made me realize we've been thinking about approval workflows all wrong. We treat consent like it's sticky—like once someone clicks "approve," that decision persists in some magical way. But consent isn't a session property. It's conditional. It's bound to specific evidence at a specific moment. When the evidence changes, the approval should expire. Period.
The article I read about this changed how I think about every approval flow I write now. Let me walk you through why this matters.
The Problem With Static Approvals
Here's the thing: most systems I've worked with treat an approval as a boolean. You click the button. It turns green. It stays green until someone closes the tab or logs out. The actual data that justified that click? Nobody's watching that.
In my refund case, the approval envelope should have looked something like this: "Reviewer authorized 12 specific orders, maximum $430, based on evidence snapshot X, at timestamp Y." When the system refreshed and found 19 orders instead, it should have said "sorry, that approval is void now" and asked for a new one.
Instead, we just let it execute. This is how you accidentally issue incorrect refunds, wrong permissions, or delete data you shouldn't have touched.
Versioning Decisions, Not Just Data
The original article frames this brilliantly: approvals need to be versioned just like code. Not just the action (refund 12 orders), but also:
- The evidence that justified it (which orders, timestamps, sources)
- The consequence (exact monetary impact, permission scope)
- The scope (the exact affected set, not a vague count)
When any of those change materially, the approval expires. The key word is materially—not every tiny data refresh should blow up an approval. There's a real distinction between changing "reviewed by alice@company.com" and changing "now 7 extra orders included."
I started defining what counts as material change in my recent work. Changed the number of affected records? Material. Changed the total monetary consequence? Material. Rewording the description? Not material. Same evidence, different timestamp? Not material.
What a Proper Approval Card Should Show
This is where I had to slow down and think. Most approval cards I've built show a summary and maybe a confidence percentage from the AI. That's essentially useless when things change.
A proper card needs:
Decision evidence first. Not buried in a tab. Not hidden behind "show details."
Exact scope. How many records? Can I click through them? Not "approximately 12"—exactly these 12.
Clear consequences. Money? Permissions? Deletions? I need to know what's irreversible.
Uncertainty called out. What assumptions is the AI making? What cases might be excluded?
Reversibility window. If I approve, how long do I have to undo it?
Validity rules. When does this approval expire? When I close the tab? (No.) When evidence changes? (Yes.)
My Take: This Is a Safety Problem Wearing a UX Mask
I agree with the original article that confidence percentages are security theater. They make reviewers feel informed without actually being informed. I've seen too many "90% confident" suggestions turn out to be wildly wrong.
What I'd push back on slightly: I don't think this solves itself through better UX alone. You need server-side validation. The browser can't be trusted. A stale tab could send a three-day-old approval token. Your server needs to compare the approved envelope with the execution envelope and reject mismatches.
Also, I'm cautious about how strictly to apply expiration rules. If you're too aggressive—expiring on every tiny change—you train reviewers to just reflexively approve the new version without thinking. You need monitoring. If you see patterns of people approving without reading the diff, something's wrong.
A Practical Implementation Angle
Here's roughly how I'd structure the approval envelope in code:
interface ApprovalEnvelope {
actionId: string;
actionRevision: number;
evidenceRevision: number;
materialFields: {
affectedCount: number;
affectedIds: string[];
consequenceUSD: number;
scope: string;
};
approvedBy: string;
approvedAt: Date;
expiresAt: Date;
expirationRules: {
affectedCountChanges: boolean;
consequenceThresholdCrossed: boolean;
evidenceBecomesUnavailable: boolean;
};
}
// Before execution, compare current state to approval envelope
function isApprovalStale(approved: ApprovalEnvelope, current: ApprovalEnvelope): boolean {
return approved.evidenceRevision !== current.evidenceRevision ||
approved.materialFields.affectedCount !== current.materialFields.affectedCount ||
approved.materialFields.consequenceUSD !== current.materialFields.consequenceUSD;
}
The Real Question
This makes me wonder: how many production systems I've built are silently executing approvals against stale evidence right now? Have you audited your approval workflows? Do you know what evidence justified the last approval that executed?
Source: This post was inspired by "Expire AI Approval When the Evidence Changes, Not When the Screen Closes" by Dev.to. Read the original article