// 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" }); });