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
97
98
99
100
101
102
103
104
105
106
// node --test examples/node-hono/test.mjs (needs `npm install` here, `cargo wasm`, `cargo host`; skips without hono)
import assert from "node:assert/strict";
import { mkdtemp } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { test } from "node:test";
import { atlibs, scopeFixture } from "../../rust/host/conformance.mjs";
import { contextOptions, createNodeContext } from "../../javascript/src/server/index.js";
const hono = await import("hono").catch(() => null);
test("a Hono app mounts clientMetadataHandler and runs a staged module", { skip: !hono && "npm install in examples/node-hono" }, async () => {
const { createApp } = await import("./server.mjs");
const dir = await mkdtemp(join(tmpdir(), "atlibs-hono-"));
await atlibs(["stage", "--target", "server", "--out", dir, "compose", "vibescrobble"]);
const ctx = createNodeContext(contextOptions(join(dir, "state")));
const app = await createApp(join(dir, "stage.json"), { ctx, call: async () => ({}), origin: "https://site.example" });
try {
const doc = await (await app.fetch(new Request("https://site.example/oauth/vibescrobble/client-metadata.json"))).json();
assert.equal(doc.client_id, "https://site.example/oauth/vibescrobble/client-metadata.json");
assert.equal((await app.fetch(new Request("https://site.example/oauth/nope/client-metadata.json"))).status, 404);
const body = JSON.stringify({ call: { input: { n: 4 } } });
const run = (url, headers = {}) => app.fetch(new Request(url, { method: "POST", body, headers: { "content-type": "application/json", ...headers } }));
const ran = await (await run("https://site.example/run/compose/even", { origin: "https://site.example" })).json();
assert.deepEqual(ran.result, { allow: true, violations: [] });
assert.equal((await run("http://127.0.0.1:8788/run/compose/even")).status, 200, "loopback, no Origin (curl)");
// review 3c H1: a cross-site page (no-cors text/plain, or another Origin) and DNS rebinding (Host) are refused.
assert.equal((await run("https://site.example/run/compose/even", { "content-type": "text/plain" })).status, 415);
assert.equal((await run("https://site.example/run/compose/even", { origin: "https://evil.example" })).status, 403);
assert.equal((await run("http://127.0.0.1:8788/run/compose/even", { origin: "https://evil.example" })).status, 403);
assert.equal((await run("http://evil.example:8788/run/compose/even")).status, 403);
assert.equal((await run("https://site.example/run/compose/even", { "content-type": "application/json; charset=utf-8" })).status, 200);
assert.equal((await app.fetch(new Request("https://site.example/.well-known/did.json"))).status, 404, "no session record declares app");
} finally {
ctx.close();
}
});
test("a session record that declares app: the server serves the app's did:web and its read-only repo on its origin", { skip: !hono && "npm install in examples/node-hono" }, async () => {
const { createApp } = await import("./server.mjs");
const { readFile, writeFile } = await import("node:fs/promises");
const dir = await mkdtemp(join(tmpdir(), "atlibs-hono-app-"));
await atlibs(["stage", "--target", "server", "--out", dir, "vibescrobble"]);
const stage = JSON.parse(await readFile(join(dir, "stage.json"), "utf8"));
const record = stage.sessions.vibescrobble.record;
const template = new URL(record.clientMetadata.client_id).origin;
record.app = { records: [{ collection: "dev.cocore.app.registration", rkey: "self", value: { $type: "dev.cocore.app.registration", name: "vibes", returnUrls: [`${template}/done`], createdAt: "2026-11-10T00:00:00.000Z" } }], wellKnown: { "cocore-app.json": { did: `did:web:${new URL(template).host}` } } };
await writeFile(join(dir, "stage.json"), JSON.stringify(stage));
const ctx = createNodeContext(contextOptions(join(dir, "state")));
try {
const app = await createApp(join(dir, "stage.json"), { ctx, call: async () => ({}), origin: "https://site.example" });
const get = async (path) => (await app.fetch(new Request(`https://site.example${path}`))).json();
assert.equal((await get("/.well-known/did.json")).id, "did:web:site.example");
assert.deepEqual(await get("/.well-known/cocore-app.json"), { did: "did:web:site.example" });
assert.deepEqual((await get("/xrpc/com.atproto.repo.getRecord?repo=did:web:site.example&collection=dev.cocore.app.registration&rkey=self")).value.returnUrls, ["https://site.example/done"]);
const again = await createApp(join(dir, "stage.json"), { ctx, call: async () => ({}), origin: "https://site.example" });
assert.deepEqual((await (await again.fetch(new Request("https://site.example/.well-known/did.json"))).json()).verificationMethod, (await get("/.well-known/did.json")).verificationMethod, "the key is kept in the state dir");
} finally {
ctx.close();
}
});
const oauthInstalled = await import("../../javascript/src/oauth-server/index.js").then(() => true, () => false);
test("a Hono app signs users in (javascript/src/oauth-server) and runs each request as its own user", { skip: (!hono && "npm install in examples/node-hono") || (!oauthInstalled && "npm install in javascript/src/oauth-server") }, async () => {
const { createApp } = await import("./server.mjs");
const { oauthServer } = await import("../../javascript/src/oauth-server/index.js");
const { browser, fakeAtproto } = await import("../../javascript/src/oauth-server/fake.mjs");
const ORIGIN = "https://site.example";
const dir = await mkdtemp(join(tmpdir(), "atlibs-hono-oauth-"));
await atlibs(["stage", "--target", "server", "--out", dir, "statusphere"]);
let app;
const fake = await fakeAtproto({ fetchClient: (url) => app.fetch(new Request(url)) });
const ctx = createNodeContext(contextOptions(join(dir, "state")));
try {
const oauth = await oauthServer(ctx, { origin: ORIGIN, scope: "atproto transition:generic", fetch: (i, n) => fetch(i, n), handleResolver: fake.base, plcDirectoryUrl: fake.base, allowHttp: true });
app = await createApp(join(dir, "stage.json"), { ctx, call: async () => Promise.reject(new Error("no operator account")), origin: ORIGIN, oauth });
const handles = {};
for (const user of ["alice", "bob"]) {
const b = browser((url) => (url.startsWith(ORIGIN) ? (req) => app.fetch(req) : fetch));
await b.go(`${ORIGIN}/oauth/login?handle=${user}.test`);
handles[user] = b.cookie(ORIGIN, "atlibs_session");
assert.ok(handles[user], `${user} signed in`);
}
const run = (handle) => app.fetch(new Request(`${ORIGIN}/run/statusphere/set_status`, { method: "POST", headers: { "content-type": "application/json", authorization: `Bearer ${handle}` }, body: JSON.stringify({ status: "🙂", now: new Date().toISOString() }) })).then((r) => r.json());
const ran = await Promise.all([handles.alice, handles.bob, handles.alice, handles.bob].map(run));
ran.forEach((r, i) => assert.ok(r.result?.uri?.startsWith(`at://${fake.did(i % 2 ? "bob" : "alice")}/`), JSON.stringify(r)));
assert.ok(fake.writes.every((w) => w.sub === w.repo));
assert.equal((await app.fetch(new Request(`${ORIGIN}/run/statusphere/set_status`, { method: "POST", headers: { "content-type": "application/json", authorization: "Bearer forged" }, body: "{}" }))).status, 401);
assert.equal((await app.fetch(new Request(`${ORIGIN}/oauth/logout`, { method: "POST", headers: { authorization: `Bearer ${handles.bob}`, origin: "https://evil.example" } }))).status, 403, "a cross-site sign-out");
// two modules under the same sign-in (granted transition:generic): each run is held to its own module's session (stage.json)
const scopes = await scopeFixture();
await atlibs(["stage", "--target", "server", "--out", join(scopes, "staged"), join(scopes, "comp.json")]);
const scoped = await createApp(join(scopes, "staged", "stage.json"), { ctx, call: async () => Promise.reject(new Error("no operator account")), origin: ORIGIN, oauth });
const create = (module, collection) => scoped.fetch(new Request(`${ORIGIN}/run/${module}/caller`, { method: "POST", headers: { "content-type": "application/json", authorization: `Bearer ${handles.alice}` }, body: JSON.stringify({ nsid: "com.atproto.repo.createRecord", input: { repo: fake.did("alice"), collection, record: {} } }) })).then((r) => r.json());
fake.writes.length = 0;
assert.equal((await create("a", "com.example.a")).result.q.ok, true);
assert.equal((await create("a", "com.example.b")).result.q.error, "a may not call com.atproto.repo.createRecord with sessions sa");
assert.equal((await create("b", "com.example.a")).result.q.error, "b may not call com.atproto.repo.createRecord with sessions sb");
assert.deepEqual(fake.writes.map((w) => w.collection), ["com.example.a"]);
} finally {
ctx.close();
await fake.close();
}
});