capsite/toybox: routing carries no secrets

The ingress no longer reads labels from a Toybox-Labels header. A header
was no place for the webkey pattern: browsers can't set one on a
WebSocket, and the pattern puts the secret in-band anyway. A page keeps
it in its fragment, reaches the vat by public labels, and sends it in
the body of a call, which the vat checks like a swissnum.

A request still reaches a vat only by naming every label of its mount.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
dckcandClaude Opus 5.5 committed 2026-10-13 21:44:29 -05:00
1 parent 28b1c3c9d3
commit 193a126d1c
5 files changed
+28 -24

No files matched your search

+10 -9
View File
@@ -320,21 +320,22 @@ export class Directory extends DurableObject {
}
/**
* A request's labels: its query parameters, plus a `Toybox-Labels` header
* (JSON) for labels too secret for a URL, which ends up in logs and
* `Referer`s. A webkey page keeps such a secret in its fragment and sends
* it in the header.
* A request's labels: its query parameters.
*
* Routing carries no secrets: a URL ends up in logs and `Referer`s. A
* secret travels in-band instead, as on a webkey page: the page keeps it
* in its fragment, reaches the vat by public labels, and sends it in the
* body of a call, which the vat checks like a swissnum.
*
* @param {Request} request
*/
const requestLabels = (request) => {
const query = {};
const labels = {};
for (const [k, v] of new URL(request.url).searchParams) {
if (k in query) throw new Error(`label ${k} given twice`);
query[k] = v;
if (k in labels) throw new Error(`label ${k} given twice`);
labels[k] = v;
}
const header = request.headers.get("Toybox-Labels");
return mergeLabels(query, header ? JSON.parse(header) : {});
return Object.freeze(labels);
};
/**