OpenTree DashboardSign in

$ date -I # 2026-07-25

Private by default is the only defensible baseline for agent output

Static hosting has been public by default for its entire history, and privacy has been the paid tier. That ordering made sense when publishing was deliberate. It does not survive an author that publishes twenty times a session from whatever happens to be in its context window.

What flipped

The gap between "I wrote this" and "this is at a URL" used to contain a human decision. Now it contains a tool call. Removing the pause removes the moment where somebody would have noticed that the report has a customer's email addresses in it — so the safe state has to be the default state, not a setting the caller remembered to pass.

What private-by-default actually requires

Four things, and skipping any one of them makes the other three decorative:

The threat is not guessing, it is forwarding

Nobody brute-forces a 128-bit token. Links leak the boring way: forwarded into a group chat, pasted into a ticket, captured in a screenshot, or handed to a link-preview bot. That is why the interesting controls are the ones that survive forwarding — an email gate makes the new recipient verify, a one-time link is already spent, and expiry closes the window.

The CSP corollary

If the host serves whatever bytes it is given, a careless <script src> in agent output can exfiltrate what the page contains. Every viewer response carries a strict Content-Security-Policy: no third-party script origins, no eval. It applies to SVG opened as a document too, which is what makes byte-for-byte SVG hosting safe without rewriting the file.

The deletion corollary

"Expired" has to mean gone. An expired link answers 410 immediately, and a scheduled purge then deletes both the database row and the stored object, after which the same URL answers 404. Two codes on purpose: the first says this existed and is over, the second says nothing at all.

What it costs the author

Almost nothing, which is the point. The defaults on this deployment are:

DefaultValue
VisibilityUnlisted. The URL carries a 22-character random token; nothing is listed publicly.
Expiry7 days for a keyed publish, 24 hours for an anonymous one. Pass never to keep it.
After expiryThe row and the stored object are both deleted by a scheduled purge, not just hidden.
RobotsX-Robots-Tag: noai, noimageai, noindex on every viewer response.
ReferrersReferrer-Policy: no-referrer, so the token never leaks into someone else's logs.
ScriptsA strict Content-Security-Policy: no third-party scripts, no eval.
Sensitive dataContent is scanned before it is stored; a hit blocks the publish unless you override.
TransportHSTS with a long max-age; the viewer is HTTPS-only.

Verify it rather than believe it

Publish anything and read the headers off the viewer URL:

curl -sI https://read.botook.ai/s/YOUR_TOKEN | grep -iE 'robots|referrer|content-security'

Is an unguessable URL really access control?

It is capability-based access control: the link is the credential. That is genuinely enough for a lot of sharing, and genuinely not enough when the link will be forwarded — which is why passwords, email gates, one-time links and encryption exist on top of it.

Can I make a page public on purpose?

Yes. Public is a choice you make per link rather than a state you have to climb out of.

Does noai actually stop anyone?

It is a request, not a fence — the same status as robots.txt. The fence is that the URL is unguessable and the page can be gated. Sending the header costs nothing and removes the excuse.

What can the host itself read?

Everything, unless you use end-to-end encryption, in which case the browser encrypts before upload and the key stays in the URL fragment — which browsers never send to a server. Then the stored bytes are ciphertext to the host too.

Keep reading