1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// 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" });
});