capsite/toybox: mount lookups in SQL, not a scan in JS

Each request parsed every mount's labels and searched them in JS. Labels
now sit one per row in mount_label, indexed on (key, value): a lookup
joins the request's labels (json_each) on the index and keeps the vat
whose every label matched. The overlap check at registration is SQL too.

mount.labels keeps the whole set as JSON; mounts stored before
mount_label get their rows filled in when the schema runs. The SQL lives
in mounts-sql.js, tested on node:sqlite, old-shape state included.

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 9356f63c64
commit 7fcd251261
4 files changed
+123 -37

No files matched your search

-20
View File
@@ -51,23 +51,3 @@ export const checkUrl = (labels, url) => {
} }
}; };
/**
* Do `a` and `b` give some key different values? Flower refuses to register
* a target that doesn't conflict with every other: lookups stay unambiguous.
*
* @param {Record<string, string>} a
* @param {Record<string, string>} b
*/
export const conflict = (a, b) => Object.entries(a).some(([k, v]) => k in b && b[k] !== v);
/**
* Does `request` carry every label of `mount`, with the same values?
*
* Stricter than Flower's match (no conflict): an ingress client holds no
* constrained handle, so a label it omits must not match, or a secret
* label would protect nothing.
*
* @param {Record<string, string>} mount
* @param {Record<string, string>} request
*/
export const carries = (mount, request) => Object.entries(mount).every(([k, v]) => request[k] === v);
+53
View File
@@ -0,0 +1,53 @@
/**
* @file The ingress's mounts, in SQL: which vat serves which label set.
*
* Labels sit one per row, so a lookup can use an index; `mount.labels`
* keeps the whole set as JSON. Request and mount labels arrive as JSON
* objects, split into rows by `json_each`.
*/
export const MOUNT_SCHEMA = [
"CREATE TABLE IF NOT EXISTS mount (vat TEXT PRIMARY KEY, labels TEXT)",
"CREATE TABLE IF NOT EXISTS mount_label (vat TEXT, key TEXT, value TEXT, PRIMARY KEY (vat, key))",
"CREATE INDEX IF NOT EXISTS mount_label_kv ON mount_label (key, value)",
// mounts made before mount_label existed
`INSERT OR IGNORE INTO mount_label
SELECT m.vat, j.key, j.value FROM mount m, json_each(m.labels) j
WHERE NOT EXISTS (SELECT 1 FROM mount_label l WHERE l.vat = m.vat)`,
];
/**
* Another mount (than ?2's) whose labels conflict with none of ?1's.
* Flower's registration rule: every mount must conflict with every other.
*/
export const OVERLAP = `
SELECT 1 FROM mount m WHERE m.vat != ?2 AND NOT EXISTS (
SELECT 1 FROM mount_label l JOIN json_each(?1) r ON r.key = l.key
WHERE l.vat = m.vat AND l.value != r.value)
LIMIT 1`;
export const MOUNT = "INSERT OR REPLACE INTO mount VALUES (?1, ?2)";
export const MOUNT_LABELS = "INSERT INTO mount_label SELECT ?1, key, value FROM json_each(?2)";
export const UNMOUNT = "DELETE FROM mount WHERE vat = ?1";
export const UNMOUNT_LABELS = "DELETE FROM mount_label WHERE vat = ?1";
/**
* The mount whose every label ?1 (the request's labels) carries, with the
* same value: the labels that match, counted per vat, against how many
* the vat has. A mount with no labels matches any request.
*
* Stricter than Flower's match (no conflict): an ingress client holds no
* constrained handle, so a label it omits must not match, or a secret
* label would protect nothing.
*/
export const LOOKUP = `
SELECT m.vat, m.labels FROM mount m JOIN (
SELECT l.vat, count(*) AS hits
FROM json_each(?1) r JOIN mount_label l ON l.key = r.key AND l.value = r.value
GROUP BY l.vat
) h ON h.vat = m.vat
WHERE h.hits = (SELECT count(*) FROM mount_label WHERE vat = m.vat)
UNION ALL
SELECT m.vat, m.labels FROM mount m
WHERE NOT EXISTS (SELECT 1 FROM mount_label l WHERE l.vat = m.vat)
LIMIT 1`;
+17 -17
View File
@@ -4,7 +4,8 @@ import { DurableObject, WorkerEntrypoint } from "cloudflare:workers";
import { RpcTarget, newWebSocketRpcSession, newWorkersRpcResponse } from "capnweb"; import { RpcTarget, newWebSocketRpcSession, newWorkersRpcResponse } from "capnweb";
import { E, Far } from "@endo/far"; import { E, Far } from "@endo/far";
import { makeClient, swissnumFromBytes } from "@endo/ocapn"; import { makeClient, swissnumFromBytes } from "@endo/ocapn";
import { carries, conflict, mergeLabels, urlLabels } from "./labels.js"; import { mergeLabels, urlLabels } from "./labels.js";
import { LOOKUP, MOUNT, MOUNT_LABELS, MOUNT_SCHEMA, OVERLAP, UNMOUNT, UNMOUNT_LABELS } from "./mounts-sql.js";
import { locationOf, makeRpcNetLayer } from "./netlayer.js"; import { locationOf, makeRpcNetLayer } from "./netlayer.js";
import VAT_RUNTIME from "vat-runtime.txt"; import VAT_RUNTIME from "vat-runtime.txt";
@@ -282,14 +283,7 @@ export class Router extends WorkerEntrypoint {
export class Directory extends DurableObject { export class Directory extends DurableObject {
constructor(ctx, env) { constructor(ctx, env) {
super(ctx, env); super(ctx, env);
ctx.storage.sql.exec("CREATE TABLE IF NOT EXISTS mount (vat TEXT PRIMARY KEY, labels TEXT)"); for (const statement of MOUNT_SCHEMA) ctx.storage.sql.exec(statement);
}
#mounts() {
return this.ctx.storage.sql
.exec("SELECT vat, labels FROM mount")
.toArray()
.map(({ vat, labels }) => ({ vat, labels: JSON.parse(labels) }));
} }
/** /**
@@ -299,22 +293,28 @@ export class Directory extends DurableObject {
* @param {Record<string, string> | null} labels * @param {Record<string, string> | null} labels
*/ */
mount(vat, labels) { mount(vat, labels) {
if (labels) { const { sql } = this.ctx.storage;
const overlap = this.#mounts().find((m) => m.vat !== vat && !conflict(m.labels, labels)); this.ctx.storage.transactionSync(() => {
if (overlap) throw new Error("mount overlaps another: add a label whose value tells them apart"); sql.exec(UNMOUNT_LABELS, vat);
this.ctx.storage.sql.exec("INSERT OR REPLACE INTO mount VALUES (?, ?)", vat, JSON.stringify(labels)); if (!labels) return void sql.exec(UNMOUNT, vat);
} else { const json = JSON.stringify(labels);
this.ctx.storage.sql.exec("DELETE FROM mount WHERE vat = ?", vat); if (sql.exec(OVERLAP, json, vat).toArray().length) {
throw new Error("mount overlaps another: add a label whose value tells them apart");
} }
sql.exec(MOUNT, vat, json);
sql.exec(MOUNT_LABELS, vat, json);
});
} }
/** /**
* The mount whose labels `request` carries, if any. * The mount whose labels `request` carries, if any. Registration keeps
* mounts pairwise conflicting, so at most one can match.
* *
* @param {Record<string, string>} request * @param {Record<string, string>} request
*/ */
lookup(request) { lookup(request) {
return this.#mounts().find((m) => carries(m.labels, request)) ?? null; const [row] = this.ctx.storage.sql.exec(LOOKUP, JSON.stringify(request)).toArray();
return row ? { vat: row.vat, labels: JSON.parse(row.labels) } : null;
} }
} }
+53
View File
@@ -0,0 +1,53 @@
/** @file The ingress's mount SQL, on node:sqlite: lookup, overlap, and mounts stored before mount_label. */
import { DatabaseSync } from "node:sqlite";
import { test } from "node:test";
import assert from "node:assert/strict";
import { LOOKUP, MOUNT, MOUNT_LABELS, MOUNT_SCHEMA, OVERLAP } from "../mounts-sql.js";
const makeDb = () => {
const db = new DatabaseSync(":memory:");
for (const statement of MOUNT_SCHEMA) db.exec(statement);
const mount = (vat, labels) => {
const json = JSON.stringify(labels);
db.prepare(MOUNT).run(vat, json);
db.prepare(MOUNT_LABELS).run(vat, json);
};
const lookup = (request) => db.prepare(LOOKUP).get(JSON.stringify(request))?.vat ?? null;
const overlaps = (vat, labels) => !!db.prepare(OVERLAP).get(JSON.stringify(labels), vat);
return { db, mount, lookup, overlaps };
};
test("a request reaches the mount whose every label it carries", () => {
const { mount, lookup } = makeDb();
mount("a", { vat: "alice", key: "s3cret" });
mount("b", { vat: "bob" });
assert.equal(lookup({ vat: "alice", key: "s3cret", page: "2" }), "a");
assert.equal(lookup({ vat: "alice" }), null);
assert.equal(lookup({ vat: "alice", key: "wrong" }), null);
assert.equal(lookup({ vat: "bob" }), "b");
assert.equal(lookup({}), null);
});
test("a mount with no labels matches any request", () => {
const { mount, lookup } = makeDb();
mount("only", {});
assert.equal(lookup({ anything: "x" }), "only");
});
test("overlap: a mount must conflict with every other", () => {
const { mount, overlaps } = makeDb();
mount("a", { vat: "alice" });
assert.equal(overlaps("b", { vat: "alice", n: "2" }), true);
assert.equal(overlaps("b", { app: "x" }), true);
assert.equal(overlaps("b", { vat: "bob" }), false);
assert.equal(overlaps("a", { vat: "alice", n: "2" }), false, "a vat's own mount doesn't count");
});
test("mounts stored before mount_label are filled in when the schema runs", () => {
const db = new DatabaseSync(":memory:");
db.exec("CREATE TABLE mount (vat TEXT PRIMARY KEY, labels TEXT)");
db.prepare("INSERT INTO mount VALUES (?, ?)").run("old", JSON.stringify({ vat: "old" }));
for (const statement of MOUNT_SCHEMA) db.exec(statement);
assert.equal(db.prepare(LOOKUP).get(JSON.stringify({ vat: "old" }))?.vat, "old");
assert.equal(db.prepare(LOOKUP).get(JSON.stringify({ vat: "other" })), undefined);
});