Prufy notes
Make it stick ยท 7 min

Decisions and tradeoffs

Every choice bought something and cost something. Being able to name both is what understanding a system looks like.

The record stays after verifying
Bought
Knowing the claim is still true today
Cost
A permanent TXT record per name
Would change if
The product only needs one-time proof
Multi-perspective check
Bought
One forged reply can't verify a domain
Cost
Waiting for public resolvers to catch up
Would change if
Nothing likely
Token in plain text
Bought
It can be shown again whenever you return
Cost
Nothing real: it's public anyway
Would change if
The token ever became a secret
DNS only
Bought
Proof of the zone, not a web host
Cost
Harder for people without DNS access
Would change if
A hand-off link is the better answer
The newest proof wins
Bought
A real sale can't be blocked by a former owner
Cost
Someone with DNS access takes a name at once
Would change if
Product wants a cooling-off period
A lost race stays pending
Bought
One simple rule, with no special cases
Cost
Ownership can flip once after a true tie
Would change if
Ties turn out to matter
Temporary failures can't demote
Bought
An outage doesn't punish owners
Cost
Slower to notice some real losses
Would change if
Nothing likely
7-day grace period
Bought
An accidental removal isn't fatal
Cost
A former owner keeps access for up to a week
Would change if
Compliance needs a shorter window
A CNAME doesn't verify
Bought
The proof stays in the claimed zone
Cost
Some setups can't delegate the record
Would change if
Customers need delegation
DNSSEC recorded, not required
Bought
Unsigned domains aren't locked out
Cost
Spoofing is covered only by multi-perspective
Would change if
Signing becomes universal
Real Postgres in Docker
Bought
Concurrency tests that genuinely contend
Cost
Tests need Docker running
Would change if
Nothing likely
Vercel Cron for the worker
Bought
No server to keep running
Cost
A claim's next look can wait up to a minute, not 15 seconds
Would change if
Checks need to be faster than once a minute
Neon's pooled connection for the app
Bought
Many short-lived functions can share a few database connections
Cost
Two connection strings to keep straight: migrations use the direct one
Would change if
The app moves to long-lived servers
A separate database for previews
Bought
Test claims never reach production data
Cost
Migrations have to be applied twice
Would change if
Schema changes get frequent enough to want a copy per branch
One product, one job
Bought
Something that can be used for real, and a flow short enough to be one page
Cost
The sending records and test email from the experiments are gone, and a domain verified under the old record name has to publish the new one
Would change if
Verification goes back to being a step inside a bigger product
Sessions without sign-up
Bought
Nothing between a visitor and their first claim, and a session per device that can be revoked on its own
Cost
Clearing cookies loses access to those claims from that browser, and there's no second device yet
Would change if
People need the same domains on two devices. Magic-link sign-in fits the same table
Only the token's hash is stored
Bought
A leaked database can't sign anyone in, open a setup link or confirm an email
Cost
A lost token can't be looked up or shown again. A new one has to be made
Would change if
Nothing likely
New sessions limited per IP
Bought
One client can't mint accounts to get around the 20-claims-an-hour limit
Cost
Everyone behind one office network shares 10 an hour, and the count is per function instance
Would change if
Real traffic. It needs a shared store first
Alerts on six state changes, sent once
Bought
No noise, and an old alert can never arrive after a newer one
Cost
If Resend or a push service is down at that moment, that alert is lost
Would change if
Delivery has to be guaranteed. Then an outbox table that also handles ordering
Email confirmed before any alert
Bought
Typing someone else's address gets them one message, ever
Cost
One more step before email alerts work
Would change if
Nothing likely
A setup link is a capability
Bought
Safe to forward or paste into an agent: it reads one record and asks for a check
Cost
A helper can't get a new code, and anyone who sees the URL has the same powers for 30 days
Would change if
Helpers need more. Then scoped links, not a wider one
The page reads the phase, with one exception
Bought
The UI can't disagree with the engine about what's happening
Cost
One rule lives in the UI, and the landing page's list doesn't apply it yet
Would change if
A second client needs the same rule. Then it moves into core's view
The globe is one WebGPU shader
Bought
One object that survives route changes, with no geometry or textures to load
Cost
Browsers without WebGPU get a still gradient, and the build only parses the shader
Would change if
The fallback matters to enough visitors to deserve a WebGL path
A service worker that caches nothing
Bought
Nobody ever sees a stale verified
Cost
No offline mode at all
Would change if
Nothing likely: every page here is live status
Drizzle RC over stable
Bought
defineRelations and object-style queries
Cost
An RC API can still move
Would change if
1.0 ships

Added beyond the original spec

AdditionWhy
abandonedA phase for it, since an abandoned claim can still be opened
failed_checks, last_failureWhat CHECK_FAILED has to record
lease_owner, lease_expires_atWhat dueForCheck needs
domain_connect_statesHashed, single-use state values
LastCheck.challengeIdSo a check of an old code doesn't count against a new one
/api/dev/clockDev only, to reach time-based states by hand