~ knotless Search/
↑↓ move↵ open⇧↵ all results

johnandersen777.bsky.social/atlibs-iroh

iroh transport for atlibs hosts: com.fedfork.exec.iroh.connect in Rust (atlibs-host) and JavaScript

0
0
main
107 lines · 7.2 KB Raw History
// node --test tests/conformance.test.mjs   (needs ../atlibs: `cargo wasm` and `cargo host`, or ATLIBS_BIN; no network)
// com.fedfork.exec.iroh.connect through both CLIs' real iroh transports (js/index.js irohSession via
// ATLIBS_TRANSPORTS, src/lib.rs Iroh), dumbpipe and ssh replaced by js/fake-bin on PATH:
// the same bytes out of both. And com.fedfork.exec.http.fetch to an iroh:/// URL on both engines (runModule,
// runModuleRust over the bridge), through js/index.js's fetcher, fake-bin's ssh + relay and http-stub.mjs.
import assert from "node:assert/strict";
import { execFile, spawn } from "node:child_process";
import { mkdtemp, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { test } from "node:test";
import { promisify } from "node:util";

import { hostBin, runModuleRust } from "../../atlibs/rust/host/conformance.mjs";
import { runModule } from "../../atlibs/javascript/src/run-module/index.js";
import { irohFetch } from "../js/index.js";

// ROOT: the sibling atlibs checkout (its Node CLI, the echo module); HERE: this repo.
const ROOT = new URL("../../atlibs/", import.meta.url);
const HERE = new URL("../", import.meta.url);
const exec = promisify(execFile);
const FAKE = new URL("js/fake-bin", HERE).pathname;
const CLI = new URL("javascript/src/server/cli.mjs", ROOT).pathname;
const ECHO = new URL("target/wasm32-unknown-unknown/release/echo.wasm", ROOT).pathname;
const MANIFEST = new URL("examples/rust/echo/module.json", ROOT).pathname;
const T = "endpointabex5k47heqqkdykv2b27ydg75jjaxeucm2ej74nt34a7up6wqlkyaiaenuhi5dqom5c6l3von3tcljrfzzgk3dbpexg4mbonfzg62bonruw42zof4";
const envOf = (dir, extra) => ({ PATH: `${FAKE}:${process.env.PATH}`, HOME: process.env.HOME, ATLIBS_SERVER_STATE: join(dir, "state"), ATLIBS_TRANSPORTS: new URL("js/index.js", HERE).pathname, ...extra });
// One `session` run through both CLIs: their stdouts.
async function both(env, input) {
	const args = ["run", ECHO, MANIFEST, "session", JSON.stringify(input)];
	const rust = (await exec(hostBin(), args, { env, maxBuffer: 1 << 24 })).stdout;
	const js = (await exec(process.execPath, [CLI, ...args], { env, maxBuffer: 1 << 24 })).stdout;
	return { rust, js };
}

test("iroh sessions: raw alpn, ssh command, ssh failure and a shell stream the same through both CLIs", async () => {
	const dir = await mkdtemp(join(tmpdir(), "atlibs-iroh-session-"));
	const key = join(dir, "iroh_ed25519");
	await writeFile(key, "not a real key\n", { mode: 0o600 });
	const env = envOf(dir, { ATLIBS_IROH_KEY: key });
	const hostKeys = [{ type: "ssh-ed25519", publicKey: "AAAAC3Bare" }];
	const cases = [
		[{ ticket: `iroh://${T}`, alpn: "echo/1", send: "hello\n" }, { stdout: "ready\ngot hello\n", stderr: "", exitCode: 0, error: null }],
		[{ ticket: T, hostKeys, command: "uname -a" }, { stdout: "line 1\nline 2\n", stderr: "oops\n", exitCode: 3, error: null }],
		[{ ticket: T, hostKeys, command: "fail" }, { stdout: "", stderr: "Host key verification failed.\n", exitCode: null, error: "ssh failed: Host key verification failed." }],
		[{ ticket: T, hostKeys, send: "hello\nexit\n" }, { stdout: "$ hello\n$ ", stderr: "", exitCode: 0, error: null }],
	];
	for (const [input, expected] of cases) {
		const { rust, js } = await both(env, input);
		assert.deepEqual(JSON.parse(js).result, expected, JSON.stringify(input));
		assert.equal(rust, js, JSON.stringify(input));
	}
});

// fix3-extra #1, 3a L2: dumbpipe's "using secret key <hex>" line never reaches a module (each spawn gets a
// fresh IROH_SECRET), and a dumbpipe that floods stderr fails with a bounded tail, through both CLIs' sessions.
test("iroh: no secret-key line reaches the module; a flood of stderr fails with its last 16 KiB", async () => {
	const env = envOf(await mkdtemp(join(tmpdir(), "atlibs-iroh-secret-")));
	const result = async (input) => Object.values(await both(env, input)).map((out) => JSON.parse(out).result);
	for (const r of await result({ ticket: T, alpn: "secret/1" })) assert.deepEqual(r, { stdout: "ok\n", stderr: "", exitCode: 0, error: null });
	const [rust, js] = await result({ ticket: T, alpn: "noisy/1" });
	assert.equal(rust.error, js.error);
	assert.ok(rust.error.startsWith("dumbpipe exited 1: x") && rust.error.endsWith("last line"), rust.error.slice(0, 40));
	assert.ok(rust.error.length <= "dumbpipe exited 1: ".length + 16384, `${rust.error.length}`);
});

// review 4a M3: a one-shot exchange keeps at most 512 KiB of what the peer sends, kills it there and says
// truncated, the same through both CLIs (the module gets it: under its 1 MiB input).
test("iroh: a one-shot call that floods stdout is cut at 512 KiB and marked truncated through both CLIs", async () => {
	const env = envOf(await mkdtemp(join(tmpdir(), "atlibs-iroh-flood-")));
	const args = ["run", ECHO, MANIFEST, "connect", JSON.stringify({ ticket: T, alpn: "flood/1" })];
	const started = performance.now();
	const rust = (await exec(hostBin(), args, { env, maxBuffer: 1 << 24 })).stdout;
	const js = (await exec(process.execPath, [CLI, ...args], { env, maxBuffer: 1 << 24 })).stdout;
	assert.ok(performance.now() - started < 10000, "killed at the cap, not run to its end");
	assert.deepEqual(JSON.parse(js).result, { output: "x".repeat(1 << 19), truncated: true });
	assert.equal(rust, js);
});

test("http.fetch to iroh:///<ref>/<socket>/mcp through both engines' scheme dispatch, allowed as iroh://*", async () => {
	const dir = await mkdtemp(join(tmpdir(), "atlibs-iroh-http-"));
	const key = join(dir, "iroh_ed25519");
	await writeFile(key, "not a real key\n", { mode: 0o600 });
	const sock = join(dir, "shell.sock");
	const stub = spawn(process.execPath, [join(FAKE, "http-stub.mjs"), sock], { stdio: ["ignore", "pipe", "inherit"] });
	await new Promise((r) => stub.stdout.once("data", r));
	const fetch = irohFetch({ key, spawn: (cmd, args, options) => spawn(join(FAKE, cmd), args, options) });
	try {
		const ref = Buffer.from(JSON.stringify({ ticket: T, hostKeys: [{ type: "ssh-ed25519", publicKey: "AAAAC3Bare" }] })).toString("base64url");
		const url = `iroh:///${ref}/${encodeURIComponent(sock)}/mcp`;
		const HTTP = "com.fedfork.exec.http.fetch";
		// the handler stands in for the wasm export (atlibs run-module protocol.test.mjs's ctxOf)
		const handler = ({ event }) => (event.type === "start" ? { calls: [{ id: "post", nsid: HTTP, input: { method: "POST", url, headers: { "content-type": "application/json" }, body: '{"jsonrpc":"2.0","id":1,"method":"ping"}' } }] } : { result: event.ok ? event.output : event.error });
		const ctx = { wasm: { run: async ({ input }) => handler(input) } };
		const mod = { module: new Uint8Array(), calls: [HTTP], http: ["iroh://*"] };
		for (const [name, run] of [["runModule", runModule], ["runModuleRust", runModuleRust]]) {
			const ran = await run(ctx, mod, "go", {}, async () => assert.fail("never the XRPC call"), { http: { "iroh://*": {} }, fetchers: { "iroh:": fetch } });
			assert.equal(ran.error, undefined, name);
			assert.equal(ran.result.status, 200, `${name}: ${JSON.stringify(ran.result)}`);
			const seen = JSON.parse(ran.result.body);
			assert.deepEqual([seen.method, seen.url, seen.body, seen.headers.host], ["POST", "/mcp", '{"jsonrpc":"2.0","id":1,"method":"ping"}', "guest"], name);
		}
	} finally {
		fetch.close();
		stub.kill();
	}
});