Diffinery

codician/diffinerypublic

Open-source, agent-first GitHub and GitHub Actions alternative that runs on your own Cloudflare account: git hosting, pull requests, code review and drop-in GitHub Actions YAML on Workers, Durable Objects, R2 and Containers.

81 lines · 4.9 KBRaw History
1import { describe, expect, it } from "vitest";
2import { Directory, type Account, type Repo } from "../../src/lib/directory.js";
3import { testD1 } from "./stubs/d1.js";
4import type { Env } from "../../src/env.js";
5
6/**
7 * Who can see what, by the batched lookups (reposVisibleTo, publicRepos, readersOf) against the
8 * one-at-a-time roleFor they stand in for.
9 */
10function world() {
11 const DB = testD1();
12 const t = "2026-10-01T00:00:00.000Z";
13 const acct = DB.sqlite.prepare("INSERT INTO accounts (id, login, kind, status, site_admin, owner_id, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)");
14 acct.run("ada", "ada", "user", "active", 0, null, t);
15 acct.run("bob", "bob", "user", "active", 0, null, t);
16 acct.run("cy", "cy", "user", "active", 0, null, t);
17 acct.run("dee", "dee", "user", "disabled", 0, null, t);
18 acct.run("root", "root", "user", "active", 1, null, t);
19 acct.run("bot", "ada-bot", "agent", "active", 0, "ada", t);
20 acct.run("acme", "acme", "org", "active", 0, null, t);
21 acct.run("shut", "shut", "org", "active", 0, null, t);
22 DB.sqlite.prepare("UPDATE accounts SET base_role = 'none' WHERE id = 'shut'").run();
23 const member = DB.sqlite.prepare("INSERT INTO org_members (org_id, user_id, role, created_at) VALUES (?, ?, ?, '2026-10-01')");
24 member.run("acme", "bob", "member");
25 member.run("shut", "bob", "member");
26 member.run("shut", "cy", "admin");
27 const repo = DB.sqlite.prepare("INSERT INTO repos (id, owner_id, name, visibility, created_at, updated_at, pushed_at) VALUES (?, ?, ?, ?, ?, ?, ?)");
28 repo.run("r-ada", "ada", "notes", "private", t, t, "2026-10-02T00:00:00.000Z");
29 repo.run("r-acme", "acme", "app", "private", t, t, "2026-10-03T00:00:00.000Z");
30 repo.run("r-shut", "shut", "vault", "private", t, t, "2026-10-04T00:00:00.000Z");
31 repo.run("r-shut-pub", "shut", "site", "public", t, t, "2026-10-05T00:00:00.000Z");
32 repo.run("r-pub", "cy", "tool", "public", t, t, "2026-10-06T00:00:00.000Z");
33 DB.sqlite.prepare("UPDATE repos SET description = 'A fast 100% thing', topics = '[\"cli\"]' WHERE id = 'r-pub'").run();
34 DB.sqlite.prepare("INSERT INTO repo_access (repo_id, account_id, role) VALUES ('r-ada', 'cy', 'read')").run();
35 const dir = new Directory({ DB } as unknown as Env);
36 return { dir };
37}
38
39const ids = (rs: Repo[]) => rs.map((r) => r.id);
40
41describe("repository visibility at scale", () => {
42 it("lists the repositories an account works with, not every public one", async () => {
43 const { dir } = world();
44 const get = async (id: string) => (await dir.account(id))!;
45 expect(ids(await dir.reposVisibleTo(await get("ada")))).toEqual(["r-ada"]);
46 // bob: acme's repository as a member (base read), shut's public one but not its private one (base none).
47 expect(ids(await dir.reposVisibleTo(await get("bob")))).toEqual(["r-shut-pub", "r-acme"]);
48 // cy: own public repo, shut's as an admin, ada's shared with them.
49 expect(ids(await dir.reposVisibleTo(await get("cy")))).toEqual(["r-pub", "r-shut-pub", "r-shut", "r-ada"]);
50 // An agent sees what its owner works with.
51 expect(ids(await dir.reposVisibleTo(await get("bot")))).toEqual(["r-ada"]);
52 expect(await dir.reposVisibleTo(await get("dee"))).toEqual([]);
53 // One owner's repositories still include its public ones for anyone.
54 expect(ids(await dir.reposVisibleTo(await get("ada"), "cy"))).toEqual(["r-pub"]);
55 expect(ids(await dir.reposVisibleTo(await get("ada"), "shut"))).toEqual(["r-shut-pub"]);
56 });
57
58 it("finds public repositories by words and owners in D1", async () => {
59 const { dir } = world();
60 expect(ids(await dir.publicRepos(10))).toEqual(["r-pub", "r-shut-pub"]);
61 expect(ids(await dir.publicRepos(10, { words: ["TOOL"] }))).toEqual(["r-pub"]);
62 expect(ids(await dir.publicRepos(10, { words: ["100%", "cli"] }))).toEqual(["r-pub"]);
63 // % and _ are matched literally.
64 expect(ids(await dir.publicRepos(10, { words: ["1_0"] }))).toEqual([]);
65 expect(ids(await dir.publicRepos(10, { words: ["shut/"] }))).toEqual(["r-shut-pub"]);
66 expect(ids(await dir.publicRepos(10, { owners: ["SHUT"] }))).toEqual(["r-shut-pub"]);
67 });
68
69 it("finds a repository's readers in a few queries, as roleFor would one by one", async () => {
70 const { dir } = world();
71 const everyone = (await dir.accountsByIds(["ada", "bob", "cy", "dee", "root", "bot", "acme", "nobody"])) as Account[];
72 expect(everyone.map((a) => a.id).sort()).toEqual(["acme", "ada", "bob", "bot", "cy", "dee", "root"]);
73 for (const id of ["r-ada", "r-acme", "r-shut", "r-shut-pub", "r-pub"]) {
74 const repo = (await dir.repoById(id))!;
75 const want = new Set<string>();
76 for (const a of everyone) if (a.kind !== "org" && (await dir.roleFor(a, repo))) want.add(a.id);
77 expect([...(await dir.readersOf(repo, everyone))].sort(), id).toEqual([...want].sort());
78 }
79 expect((await dir.accountsByLogins(["ADA", "ada-bot", "ghost"])).map((a) => a.id).sort()).toEqual(["ada", "bot"]);
80 });
81});