2
4 Comments

StareBrain build log: "denied" and "verified not to have happened" are different claims

Spent the week refining confirm-before-execute UX — first reframing risk as recoverability, then recoverability as "how far did the consequence already travel before undo." Today got pushed on something sharper: my system only tracks two states, blocked and executed. There's a third I've been quietly skipping.

Got a framework for it that broke a bug fix I thought was already solved. Last week I found a race condition where a stale result from an earlier attempt rendered as "executed" right after the current attempt correctly denied. My fix: tag every attempt with an ID, drop stale results that don't match. Bug gone, or so I thought.

The gap: my denial log says "blocked," and that's true about the decision. It says nothing about whether the target system actually stayed clean. I check that the new attempt doesn't fire wrong. I never independently verify nothing landed from an old one — I just trust the stale-drop was enough.

Real model needs three separate guarantees, not one: the denied attempt never crosses the execution boundary, any earlier in-flight attempt gets cancelled or fenced off, and — the one I'm missing — independent verification that no side effect actually occurred downstream. If you can't prove all three, the honest verdict isn't "blocked." It's "insufficient evidence."

For something like a sent text, that third check might never fully close — I can't query someone's phone to confirm a message didn't arrive. So "insufficient evidence" may end up a permanent state for certain actions, not a temporary one I eventually resolve.

Also ran a real test today instead of just theorizing: pulled a dependency-invalidation library, wrote the stale-booking scenario myself, ran it in a clean environment. It blocked correctly. First thing all week I verified instead of took on faith.

Building in public, mistakes and all — link in profile if you want to follow along.

posted toAvatar for product StareBrain
StareBrain
  1. 1
    This distinction feels especially important in protection systems: a system can know what decision it made without necessarily knowing what happened downstream. I've run into a similar design question while working on safeguards for a software system. It changed how I think about status messages: "denied" describes the decision, while "no side effect occurred" is a much stronger claim that requires evidence. That makes "insufficient evidence" a surprisingly valuable state. It prevents the protection layer from turning uncertainty into false reassurance.
    1. 1

      Good to see this land the same way from a completely different domain — you're describing protection-system safeguards, I'm describing phone commands, and we both ended up at "the decision and the downstream fact are not the same claim." That's usually a decent signal the distinction is real rather than something I talked myself into over one bug.

      Someone else on a related thread pushed this into something more concrete that might be useful for your side too: instead of collapsing everything non-executed into one "denied" bucket, split it into denied-and-verified-clean vs. denied-but-can't-confirm-downstream-state. The second one doesn't get to claim "no side effect occurred" — it only gets to claim "didn't cross the boundary I can see," which is a narrower and more honest thing to say. Turning "insufficient evidence" into its own permanent, nameable state (not just a temporary in-between) is what actually stops it from quietly getting rounded up to "safe" over time.

      Curious what your protection system currently does with that gap — does it have a state between "blocked" and "confirmed safe," or does everything non-blocked collapse into one bucket right now the way mine did before this week?

      1. 1
        We don't currently have a separate state between “blocked” and “confirmed safe.” But in our case, the protection decision carries quite a bit of context, so we don't treat those states as simply “blocked” and “everything else is safe.” When a specific protected route is blocked, we know what operation was prevented and the state we control remains known in that context. The same applies in the other direction when something is consciously allowed for a superadmin — that is an explicit policy decision, not an unknown state. Where the distinction you are describing becomes important is beyond that boundary. We can know that our controlled operation was prevented or intentionally allowed, while downstream effects through another channel may still be outside what we can verify. So we don't have a named middle state today, but the reasoning is contextual rather than treating non-blocked outcomes as one bucket.
        1. 1

          That's a genuinely important distinction from what I'd assumed — "no named middle state" isn't the same as "one undifferentiated bucket." Knowing exactly what was blocked or explicitly allowed, and only having the gap live beyond your own controlled boundary, is actually a narrower and more honest problem than the one I was describing. My "blocked" bucket really was flattening everything, yours has structure right up to the edge of what you can see.

          There's a live discussion happening on a different thread today that's basically trying to name your exact edge case — several people converging on splitting "denied" into denied-and-verified-clean vs. denied-but-downstream-unresolved, plus making that unresolved state permanent and nameable rather than temporary. Sounds like your system already has the reasoning for that distinction, it just doesn't have a label for the specific moment where "I know what I decided" stops overlapping with "I know what happened as a result." Might be worth naming that edge explicitly even without building anything new — just so it's visible in the record rather than living only in how your team reasons about it informally.