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

johnandersen777.bsky.social/atlibs-cocore

0
0
main
96 lines · 5.9 KB Raw History
// node --test web/cocore/cocore-page.test.mjs  (after `cargo wasm`)
// The page logic with the real modules, runModule, policyCall and the Node wasm runner; only the OAuth
// session (its fetchHandler: the user's PDS and what it proxies) is stubbed.
import assert from "node:assert/strict";
import { mkdtemp } from "node:fs/promises";
import { registerHooks } from "node:module";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { test } from "node:test";

// The page resolves atlibs/ through its import map; Node gets the same mapping here.
registerHooks({
	resolve(specifier, context, next) {
		const lib = specifier.startsWith("atlibs/") && new URL(`./atlibs/${specifier.slice("atlibs/".length)}`, import.meta.url).href;
		return next(lib || specifier, context);
	},
});
const { NAMES, loadPolicy, runAction } = await import("./cocore-page.js");
const { appRepo, appRepoAnswer, requestScope } = await import("atlibs/oauth/index.js");
const { localModule } = await import("atlibs/run-module/index.js");
const { createNodeContext, fileFetch } = await import("atlibs/server/index.js");

const did = "did:plc:lpfuqerea3deuoyrn7ojser4";
const base = new URL("./", import.meta.url);
const modules = Object.fromEntries(NAMES.map((name) => [name, localModule(new URL(`modules/${name}.wasm`, base), new URL(`modules/${name}.json`, base), fileFetch)]));
const policy = await loadPolicy(base, fileFetch);
const ctx = createNodeContext({ id: "cocore-test", stateDir: await mkdtemp(join(tmpdir(), "cocore-")) });

// The user's PDS: mints service auth, proxies the console's key calls. cocore.dev answers chat completions.
function session(seen) {
	return {
		did,
		async fetchHandler(path, init) {
			seen.push({ path, proxy: init.headers["atproto-proxy"] });
			if (path.startsWith("/xrpc/com.atproto.server.getServiceAuth")) return Response.json({ token: "svc-token" });
			if (path.startsWith("/xrpc/dev.cocore.account.listApiKeys")) return Response.json({ keys: [] });
			return Response.json({ error: "InvalidRequest" }, { status: 400 });
		},
	};
}
const cocore = (seen) => ({
	...ctx,
	http: {
		fetch: async (url, init) => {
			seen.push({ url: String(url), authorization: init?.headers?.authorization });
			if (String(url).endsWith("/models")) return Response.json({ object: "list", data: [{ id: "stub" }] });
			if (!init.headers.authorization) return Response.json({ error: { message: "Missing Authorization: Bearer header", type: "authentication_error", code: null } }, { status: 401 });
			return Response.json({ model: "stub", choices: [{ message: { role: "assistant", content: "Hi there" }, finish_reason: "stop" }], usage: {} });
		},
	},
});

test("one sign-in asks for every module's scope", () => {
	const scope = requestScope(policy, NAMES).split(" ");
	assert.ok(scope.includes("rpc:dev.cocore.inference.dispatch?aud=*"));
	assert.ok(scope.includes("rpc:dev.cocore.account.createApiKey?aud=did:web:cocore.dev%23cocore_console"));
	assert.ok(!scope.some((s) => s.startsWith("transition:") || s.includes("appview")));
});

test("chat: the page's host mints a service-auth token from the session for cocore.dev", async () => {
	const seen = [];
	const result = await runAction({ ctx: cocore(seen), policy, modules, session: session(seen) }, "cocore-inference", "chat", { prompt: "hello" });
	assert.equal(result.text, "Hi there");
	assert.deepEqual(seen.map((s) => s.path?.split("?")[0] ?? s.url), ["/xrpc/com.atproto.server.getServiceAuth", "https://cocore.dev/api/v1/chat/completions"]);
	assert.match(seen[0].path, /aud=did%3Aweb%3Acocore.dev&lxm=dev.cocore.inference.dispatch/);
	assert.equal(seen[1].authorization, "Bearer svc-token");
});

test("a module is held to its own session: keys cannot mint inference tokens", async () => {
	const narrowed = { ...policy, sessions: { ...policy.sessions, "cocore-inference": policy.sessions["cocore-keys"] } };
	await assert.rejects(runAction({ ctx: cocore([]), policy: narrowed, modules, session: session([]) }, "cocore-inference", "chat", { prompt: "x" }), /needs a service-auth token .*cocore-inference may not call com.atproto.server.getServiceAuth/);
	const seen = [];
	assert.deepEqual(await runAction({ ctx: cocore(seen), policy, modules, session: session(seen) }, "cocore-keys", "list_keys", {}), { keys: [] });
	assert.deepEqual(seen.map((s) => [s.path.split("?")[0], s.proxy]), [["/xrpc/dev.cocore.account.listApiKeys", "did:web:cocore.dev#cocore_console"]]);
});

test("signed out: the model directory works, inference is cocore's 401", async () => {
	const seen = [];
	assert.deepEqual((await runAction({ ctx: cocore(seen), policy, modules }, "cocore-inference", "models", {})).data, [{ id: "stub" }]);
	await assert.rejects(runAction({ ctx: cocore(seen), policy, modules }, "cocore-inference", "chat", { prompt: "x" }), /co\/core HTTP 401 authentication_error: Missing Authorization/);
	assert.ok(seen.every((s) => s.authorization === undefined));
});

test("the app registration: served as the deployment's own did:web, valid for co/core's device pairing", async () => {
	const record = await (await fileFetch(new URL("records/cocore-inference.json", base))).json();
	const repo = await appRepo({ "cocore-inference": record }, { origin: "https://cocore.atlibs.dev", publicKeyMultibase: "zDnaeTest" });
	assert.equal(repo.did, "did:web:cocore.atlibs.dev");
	const [status, , body] = appRepoAnswer(repo, "/xrpc/com.atproto.repo.getRecord?repo=did:web:cocore.atlibs.dev&collection=dev.cocore.app.registration&rkey=self");
	assert.equal(status, 200);
	const { value } = JSON.parse(body);
	// co/core's checks (packages/appview/src/devicepair/app-registration.ts): a name of 1..40, https return URLs
	assert.ok(value.name.length > 0 && value.name.length <= 40);
	assert.deepEqual(value.returnUrls, ["https://cocore.atlibs.dev/"]);
	assert.equal(value.website, "https://cocore.atlibs.dev");
	assert.deepEqual(JSON.parse(appRepoAnswer(repo, "/.well-known/cocore-app.json")[2]), { did: "did:web:cocore.atlibs.dev" });
});