Theseus: warn before opening a name a blocklist flags

The blocklist consumer existed in the resolver library and the gateway, but
the browser opened a flagged name without comment. Now the indexer process
reads the subscribed lists from the chain every ten minutes and hands the
flags to main. A flagged name loads a warning page naming the reason, the
list and the report; the user may continue, and that is remembered per name.

Two gates, because content is reached two ways. loadBns shows the real
interstitial. serveBns refuses with an inline page on every path that skips
it: reload, back and forward, bns:// links, web app windows. The inline page
has no button, since a page at the site's own origin must not be able to
approve itself; only blocked.html may ask to continue, checked by file URL.

Settings › Naming has the policy: warn (default), never open, or ignore the
lists. The csam reason is never offered a way through. A list that cannot be
read keeps the last known flags and never stops a name from resolving.

The gateway put its own warning in front of flagged sites, which this
browser could not get past: it fetches files itself, with no cookie jar. It
now sends x-bns-policy: client and the gateway stays out of the way for a
client that says it decides for itself.

dev/blocklist-selftest.js runs the real protocol handler and decision
functions against a scratch profile.
This commit is contained in:
Local Dev 2026-10-04 15:50:35 +02:00
parent 9f6dd69bf3
commit 3c04f971a9

View file

@ -619,7 +619,13 @@ async function serve(res, name, reqPath, baseHref, req = null) {
});
return res.end();
}
if (refuse || !hasBlockAck(req, entry.name)) {
// A resolver client (Theseus, Ariadne) fetches a site's files itself and
// shows its OWN warning with its own "continue"; it cannot use this one,
// having no cookie jar and a different origin. It says so with
// "x-bns-policy: client", and the gateway then stays out of the way. A
// browser navigation cannot send that header, so visitors are still warned.
const clientDecides = String(req?.headers?.["x-bns-policy"] || "").toLowerCase() === "client";
if (refuse || (!clientDecides && !hasBlockAck(req, entry.name))) {
u.searchParams.set("bns-proceed", "1");
res.writeHead(refuse ? 451 : 403, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store" });
return res.end(blockPage(entry, refuse ? null : `${root}${u.pathname}${u.search}`));