Skip to main content
A check is four steps. Only the first one decides whether you are proved; the other three exist so that a negative comes back with a reason attached.

Recursive resolvers decide

A TXT query for _ownsi-challenge.acme.com goes to Google, Cloudflare and Quad9 in parallel, over DNS-over-HTTPS. Majority of three wins.Public resolvers are used rather than the authoritative nameservers because they are what the rest of the internet sees. A record that only your own nameservers know about is not published yet, and calling that “proved” would be proving something nobody else can check.

The authoritative nameservers explain

Only on a negative. ownsi walks the labels up to the real authoritative zone, queries its nameservers directly over UDP/53, and reads the SOA.This is the step that separates “you have not created the record” from “you created it and the internet has not caught up”. Those look identical from a recursive resolver and need completely different sentences.

Twelve probes pattern-match

The probes run over the observation already collected — no further network. Each one recognises one specific shape of wrongness and produces a diagnosis with its own cause and fix.

A pure function transitions the claim

(claim, diagnosis, now) in; the new state, the events to emit, and when to check next, out. No I/O, so the whole transition table is testable without DNS.

The three outcomes

Every attempt ends in exactly one of these, and the third is not a failure of the second.

found

The token is published and the majority of resolvers agree. The claim is proved.

absent

Resolvers answered, and the token is not there. This is where a diagnosis is produced.

unresolvable

We could not get a trustworthy answer. This changes nothing — no state transition, no email, no consecutive-failure count.
unresolvable being inert is deliberate. A resolver outage on our side must never look like your record disappearing, and must never send you an email telling you it did. A mass outage sends zero emails.

When the next check happens

nextCheckAt is derived, not a fixed interval. It comes from the claim’s age, its consecutive failure count, and the zone’s SOA MINIMUM. That last input is why the waiting screen can be specific. RFC 2308 says the SOA MINIMUM is exactly how long a resolver keeps caching a “does not exist”. If your record was created two minutes ago in a zone with a 300-second MINIMUM, the resolvers are going to keep saying no for about three more minutes no matter how often anyone asks — so ownsi says “resolvers forget the ‘does not exist’ in about 3 min” and schedules itself accordingly. That is the waitEstimate block:

diagnosis or waitEstimate, never neither

A claim that is not yet proved always carries one of the two, and they mean opposite things:
  • diagnosis is set — something about the record needs to change. fix says what.
  • waitEstimate is set — nothing needs to change. secondsRemaining says how long.
Reading diagnosis first and falling back to waitEstimate gives you the whole “what now” message for any pending claim.

Reconfirmation

Proved claims are not swept on a schedule. A later claim on the same name proves on its own date, so lastConfirmedAt only ever moves forward — nothing can un-prove a domain by accident, and firstVerifiedAt is the earliest claim’s date whatever happens after it.