<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[DomScan]]></title><description><![CDATA[DomScan]]></description><link>https://domscan.hashnode.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1593680282896/kNC7E8IR4.png</url><title>DomScan</title><link>https://domscan.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Thu, 17 Sep 2026 11:24:53 GMT</lastBuildDate><atom:link href="https://domscan.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Unknown Is a Valid Result: Designing Domain Intelligence Workflows That Do Not Lie]]></title><description><![CDATA[Disclosure: I’m Esteve Castells, the maker of DomScan.

Domain intelligence often enters an application as a simple question. Is this domain available? Does this DNS record exist? Is an email security]]></description><link>https://domscan.hashnode.dev/unknown-is-a-valid-result-designing-domain-intelligence-workflows-that-do-not-lie</link><guid isPermaLink="true">https://domscan.hashnode.dev/unknown-is-a-valid-result-designing-domain-intelligence-workflows-that-do-not-lie</guid><category><![CDATA[api]]></category><category><![CDATA[dns]]></category><category><![CDATA[Security]]></category><category><![CDATA[software design]]></category><dc:creator><![CDATA[Esteve Castells]]></dc:creator><pubDate>Sun, 30 Aug 2026 20:35:30 GMT</pubDate><content:encoded><![CDATA[<blockquote>
<p>Disclosure: I’m Esteve Castells, the maker of <a href="https://domscan.net">DomScan</a>.</p>
</blockquote>
<p>Domain intelligence often enters an application as a simple question. Is this domain available? Does this DNS record exist? Is an email security control configured? Did a public identity signal appear on the website?</p>
<p>The easiest response model is a boolean. It is also frequently the wrong one.</p>
<p>Checks against public internet evidence can time out, return incomplete data, hit access restrictions, or encounter an unsupported input. If an application converts every inconclusive result into <code>false</code>, it creates confident answers that the evidence never supported.</p>
<h2>The boolean trap</h2>
<p>Imagine a domain availability check that returns no conclusive result. Mapping that response to <code>available: false</code> makes the domain look registered. Mapping it to <code>available: true</code> is worse because a user may act on it. The honest answer is that availability could not be determined from the evidence available at that time.</p>
<p>The same problem appears in security and identity workflows:</p>
<ul>
<li>A blocked reputation check does not prove a domain is safe.</li>
<li>A missing public profile does not prove the profile does not exist.</li>
<li>A failed DNS lookup does not prove the record is absent.</li>
<li>An unavailable certificate source does not prove no certificate was issued.</li>
</ul>
<p>These are not edge cases to hide. They are states the product must represent.</p>
<h2>Model evidence separately from interpretation</h2>
<p>A useful internal contract gives uncertainty its own vocabulary. For example:</p>
<pre><code class="language-ts">type EvidenceState =
  | "observed"
  | "absent"
  | "unknown"
  | "not_requested"
  | "unsupported";

interface EvidenceResult&lt;T&gt; {
  state: EvidenceState;
  value: T | null;
  checkedAt: string;
  confidence?: "high" | "medium" | "low";
  caveats: string[];
}
</code></pre>
<p>This structure separates what the check observed from what the application decides to do next. A product can still define policy, such as requiring a high-confidence result before approving a workflow, without rewriting missing evidence as a factual absence.</p>
<p>It also prevents <code>null</code> from carrying five unrelated meanings. <code>null</code> alone cannot tell a caller whether a check failed, was skipped, is unsupported, or found authoritative evidence of absence.</p>
<h2>Unknown states affect the whole system</h2>
<p>Once uncertainty becomes part of the contract, several implementation decisions improve.</p>
<p><strong>Retries become selective.</strong> An unknown caused by a timeout may be eligible for a bounded retry. An unsupported input is not.</p>
<p><strong>Caching becomes safer.</strong> A conclusive observation and a temporary unknown can use different freshness policies. The original check time should remain attached to both.</p>
<p><strong>Alerts become quieter.</strong> Monitoring can distinguish a real change from a failed observation. Losing visibility is important, but it is not the same event as proving that a record disappeared.</p>
<p><strong>Scores become explainable.</strong> A risk score can report incomplete coverage instead of silently treating every unchecked signal as neutral.</p>
<p><strong>User interfaces become more honest.</strong> Presenting “unknown” with a short caveat helps a user decide whether to retry, investigate manually, or continue with reduced confidence.</p>
<h2>Documentation is part of the data model</h2>
<p>An enum is not enough. Developers need to know what qualifies as observed or absent, when a result becomes unknown, which timestamps describe the evidence, and whether cached data was used.</p>
<p>That is why the <a href="https://domscan.net/docs">DomScan documentation</a> publishes operation inputs, outputs, costs, limits, and evidence boundaries. The goal is not to make external data look perfectly certain. It is to make its uncertainty usable.</p>
<h2>The practical lesson</h2>
<p>Building domain intelligence workflows changed how I think about API quality. A clean success response is useful, but a precise incomplete response can be more valuable than an unjustified answer.</p>
<p>Before adding another boolean to an integration, ask what happens when the evidence is blocked, stale, partial, unsupported, or never requested. If those cases collapse into the same value, the schema is hiding information your users may need.</p>
<p>Unknown is not a failure of the data model. Often, it is the most accurate result the system can return.</p>
]]></content:encoded></item></channel></rss>