johnandersen777.bsky.social/atlibs-fedproxy
fedproxy and ingress modules for atlibs: SSH public keys on your PDS, did:key ingress; pages and web tiles
0
0
// node --test web/ingress/ingress-cubit.test.mjs (after `cargo wasm`)
// The page cubit over the real ingress module, the real didkey and subscribeXrpc, with a fake relay
// behind the WebSocket class: registers, serves, gets dropped (1011), re-registers, serves again.
import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
import { registerHooks } from "node:module";
import { test } from "node:test";
registerHooks({
resolve(specifier, context, next) {
const lib = specifier.startsWith("atlibs/") && new URL(`../../../atlibs/javascript/src/${specifier.slice("atlibs/".length)}`, import.meta.url).href;
return next(lib || specifier, context);
},
});
const { IngressCubit } = await import("./ingress-cubit.js");
const { load } = await import("../../../atlibs/rust/src/harness.mjs");
const WASM = new URL("../../target/wasm32-unknown-unknown/release/ingress.wasm", import.meta.url);
const { run } = await load(WASM);
const manifest = JSON.parse(await readFile(new URL("../../modules/ingress/module.json", import.meta.url), "utf8"));
const T = "com.fedproxy.temp.xrpc.subscribe";
const nonce = () => {
const bytes = crypto.getRandomValues(new Uint8Array(64));
bytes[0] = 0; // not a JWS character, so didkey.sign takes it
return Buffer.from(bytes).toString("base64");
};
// The relay side of each subscribe socket. The first connection is dropped with 1011 after it
// answers one request; the second answers one request and the test stops the run.
function relayWorld() {
const sockets = [];
const responses = [];
class FakeRelay {
readyState = 0;
constructor(url) {
this.url = new URL(url);
this.n = sockets.push(this);
setTimeout(() => {
this.readyState = 1;
this.onopen?.();
this.push({ $type: `${T}#registered`, subdomain: this.url.searchParams.get("did").replaceAll(":", "-").toLowerCase() });
this.push({ $type: `${T}#request`, requestId: `hello-${this.n}`, method: "GET", path: "/xrpc/com.example.ingress.hello", params: { name: `socket${this.n}` }, headers: {} });
}, 5);
}
push(frame) {
this.onmessage?.({ data: JSON.stringify(frame) });
}
send(text) {
const frame = JSON.parse(text);
responses.push({ socket: this.n, ...frame });
if (frame.requestId === "hello-1") setTimeout(() => this.close(1011, "subscriber unresponsive for 90s"), 5);
}
close(code = 1005, reason = "") {
if (this.readyState > 1) return;
this.readyState = 3;
this.onclose?.({ code, reason });
}
}
return { FakeRelay, sockets, responses };
}
test("the browser host keeps its did:key in secret settings and re-registers after the relay drops it", async () => {
const settings = new Map();
const fetched = [];
const ctx = {
settings: { get: async (k) => settings.get(k) ?? null, set: async (k, v) => void settings.set(k, v) },
wasm: { run: async ({ entry, input }) => run(entry, input) },
http: {
fetch: async (url, init) => {
fetched.push(url);
assert.equal(url, "https://xrpc.fedproxy.com/xrpc/com.fedproxy.temp.xrpc.getRegistrationNonce");
assert.match(init.headers.authorization, /^Bearer /);
return new Response(JSON.stringify({ nonce: nonce() }));
},
},
};
const { FakeRelay, sockets, responses } = relayWorld();
const module = Promise.resolve({ module: new Uint8Array(await readFile(WASM)), calls: manifest.calls, didkey: manifest.didkey });
const id = "http://localhost/modules/ingress.wasm";
const cubit = new IngressCubit({ ctx, module, id, WebSocket: FakeRelay });
await cubit.init();
assert.equal(cubit.state.status, "idle");
assert.match(cubit.state.did, /^did:key:zDn/);
assert.equal(cubit.state.url, `https://${cubit.state.did.replaceAll(":", "-").toLowerCase()}.xrpc.fedproxy.com/`);
assert.ok(settings.get("didkeys")[id].d, "the private JWK is in the didkeys setting");
const again = new IngressCubit({ ctx, module, id, WebSocket: FakeRelay });
await again.init();
assert.equal(again.state.did, cubit.state.did, "same identity, same did");
const running = cubit.start({ lifetimeMs: "30000" });
const until = async (check) => {
for (let i = 0; i < 400 && !check(); i++) await new Promise((r) => setTimeout(r, 10));
assert.ok(check());
};
await until(() => responses.some((r) => r.requestId === "hello-2"));
cubit.stop();
const ran = await running;
assert.equal(ran.error, "aborted");
assert.equal(cubit.state.status, "done");
assert.deepEqual(responses.map((r) => [r.socket, r.requestId, r.status, r.body.message]), [
[1, "hello-1", 200, "hello socket1"],
[2, "hello-2", 200, "hello socket2"],
]);
assert.equal(sockets.length, 2);
assert.equal(fetched.length, 2, "a fresh nonce per registration");
assert.equal(new URL(sockets[1].url).searchParams.get("did"), cubit.state.did);
assert.ok(sockets[1].url.searchParams.get("service_auth"), "service-auth rides in the query string");
assert.equal(cubit.state.drops, 1);
assert.ok(cubit.state.log.some((line) => /relay closed: .*1011/.test(line)), cubit.state.log.join("\n"));
assert.ok(cubit.state.log.some((line) => /timer reconnect/.test(line)));
});
test("a module with no didkey services is refused before any key is made", async () => {
const ctx = { settings: { get: async () => null, set: async () => {} }, wasm: { run: async ({ entry, input }) => run(entry, input) }, http: { fetch: async () => new Response("{}") } };
const cubit = new IngressCubit({ ctx, module: Promise.resolve({ module: new Uint8Array(), calls: [], didkey: { services: [] } }), id: "x" });
await cubit.init();
assert.equal(cubit.state.status, "error");
assert.match(cubit.state.error, /didkey services/);
});
// review 3a L6: a link can name any module record; &serve starts one only after the user confirms.
test("&serve starts a module named by at:// only when confirmed; the local module at once", async () => {
const ctx = { settings: { get: async () => null, set: async () => {} } };
const module = Promise.resolve({ module: new Uint8Array(), calls: [], didkey: { services: ["https://xrpc.fedproxy.com"] } });
const asked = [];
const confirm = (answer) => (message) => (asked.push(message), answer);
const remote = new IngressCubit({ ctx, module, id: "at://did:plc:attacker/com.fedfork.exec.wasm.module/x" });
assert.equal(await remote.mayAutoServe(confirm(false)), false);
assert.equal(await remote.mayAutoServe(confirm(true)), true);
assert.match(asked[0], /at:\/\/did:plc:attacker\/com\.fedfork\.exec\.wasm\.module\/x[\s\S]*https:\/\/xrpc\.fedproxy\.com/);
asked.length = 0;
assert.equal(await new IngressCubit({ ctx, module, id: "http://localhost/modules/ingress.wasm" }).mayAutoServe(confirm(false)), true);
assert.deepEqual(asked, []);
// ?module=<handle>/<name>: the loaded record's at:// URI is the identity, so it still asks
const uri = "at://did:plc:attacker/com.fedfork.exec.wasm.module/x";
const byHandle = new IngressCubit({ ctx, module: module.then((m) => ({ ...m, id: uri })), id: "attacker.example/x" });
assert.equal(await byHandle.mayAutoServe(confirm(false)), false);
assert.match(asked[0], /Serve at:\/\/did:plc:attacker\//);
});