Why this page exists

Every other route on this site is rendered from files in this repository and asks nothing of you. The Console is the one exception: when you type a question rather than a command, that line is posted to /api/ask, a route on this site's own server. That single request is the entire privacy surface of this build, so the rest of this page describes it in the order it happens, and then lists what the browser keeps on your machine.

What the request contains

  • Your question as typed, between 1 and 800 characters. Anything longer is refused before it reaches a model.
  • Up to 4 preceding turns of the same Console conversation, each capped at 1200 characters, so a follow-up can be understood.
  • Nothing else. No account, no identifier, no reading history, no fingerprint. This site sets no cookies, so none are attached.
  • The whole body is capped at 16 KiB and must be sent as JSON from this site's own origin; a cross-origin post is rejected with 403 before it is read.

What the server does with it

  • A local answer is built first, from the same content files that render the rest of this site: a search, then a small set of quoted passages, each with a link to the page it came from.
  • If that answer covers the question, or if the optional model provider is switched off, the reply is produced entirely on this origin and your question is never sent anywhere else.
  • The reply is returned with Cache-Control: private, no-store, so no shared cache keeps a copy of it.

When a model provider is involved

The provider is off unless a deployment sets ASK_ANTHROPIC_ENABLED (or ASK_PROVIDER_ENABLED) to true and supplies a server-side ANTHROPIC_API_KEY. In production it additionally refuses to start without a rate-limit salt of at least 32 characters, an explicit trusted-proxy setting, a single-instance acknowledgement and a release acknowledgement — four switches that exist so the provider cannot be turned on by accident. Only when all of that is in place, and only for a question the local path could not answer on its own, does this site's server make one HTTPS request to https://api.anthropic.com/v1/messages.

What is sent there

  • Your question, truncated to 800 characters.
  • Up to four earlier turns of the same conversation, each truncated to 800 characters, and dropped entirely if the request would otherwise exceed its token budget.
  • A short evidence set drawn from this site's own published pages — an id, a label, a link and an excerpt per passage.
  • Nothing that identifies you: not your IP address, not a cookie, not a storage key, not your browser's headers. The connection is opened by this site's server, never by your browser — the page's Content-Security-Policy permits connections to this origin only.
  • The API key stays in the server environment and is never sent to the browser.

What comes back, and what is done with it

  • At most 300 output tokens, parsed as a single JSON object and discarded if it does not match the expected shape.
  • An answer that cites none of the passages it was given is thrown away and the local answer is shown instead, so the model cannot introduce a claim this site does not already publish.
  • A twelve-second deadline, one retry, and then the local answer in its place.
  • The model used is a small Claude model — claude-haiku-4-5 unless a deployment selects another from a fixed allowlist.

Rate limits, and the only thing that is remembered

The endpoint counts requests so it cannot be used as a free model proxy. It counts them; it does not keep them.

  • The counter key is a SHA-256 hash of a server-side salt, the current date and the caller's network address. The address itself is never stored, and because the date is part of the hash, today's key cannot be matched to yesterday's.
  • The limits are five questions a minute and thirty an hour per address, thirty a day per session, and two in flight at once. A session means an ask_session cookie where a deployment sets one; this build sets none, so it falls back to the same address.
  • Those counters live in the server process's memory. Each window resets on its own clock, all of them are lost when the process restarts, and idle keys are swept out once the table grows past five hundred. Nothing is written to a database, a file or a log.
  • A daily spend cap and a circuit breaker — five provider failures inside a minute pause it for five — close the provider path; the local answer is returned in its place.
  • The outcome hook is deliberately coarse: it can record a category, a duration and whether the provider ran, never the question or the answer. In this build it records nothing at all.

What stays in your browser

The shell keeps its own state on your machine under namespaced, versioned keys. None of it is sent anywhere, and every surface on this site works with all of it missing.

  • dt.prefs.v1 — local storage. Theme, motion, density, fidelity, zoom and the single-key-shortcut switch. It outlives the tab because a preference set once should not have to be set again.
  • dt.shell.session.v1 — session storage, this tab only. Whether the boot sequence has played, the window's position and state, and the command history that lets a reload restore your transcript.
  • dt.viewer.origin.v1 — session storage, this tab only. Where a viewer was opened from, so closing it returns you there rather than to the top of the site.
  • One further session key records that you dismissed the bar at the top of a document, for this visit only.
  • No cookies are set. Clearing this site's data in your browser removes all of it.

What this site does not do

  • No analytics, no tag manager, no pixel, no session recording, no consent wall. The build has four runtime dependencies and none of them contacts a third party.
  • No third-party embeds and no third-party fonts: the three typefaces are fetched at build time and served from this origin, so no request leaves the page to load them.
  • Two forms exist. The Console input is handled in the page, and the notes filter is a same-origin GET that puts your filter in the URL. Neither sends anything to anyone else.
  • The contact route opens a message in your own mail client. This site never receives it, because there is no endpoint here that accepts one.
  • Nothing is sold, shared or profiled, because nothing is collected to sell, share or profile.

Where to check this

Every claim above is a statement about code, not a policy: the endpoint and its limits are in app/api/ask/route.ts, the provider call and its allowlist in lib/ask/provider.ts, the counters and the hashing in lib/ask/rate-limit.ts, the empty outcome hook in lib/ask/observability.ts, the storage keys in lib/shell/persistence.ts, and the Content-Security-Policy in next.config.ts. If a line here stops matching one of those files, the line is the error.