Skip to content
75 linesCodeBlameRaw

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

The runner base keeps its old comment, so the pushed base image still matches its folder1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import type { Project, User } from "@g1t/contracts";
5
6import { can, needs, permission } from "../../../packages/contracts/src/access.ts";
7import { NEEDS, repoRef, type Method } from "./access.ts";
8
9const project = (isPrivate: boolean): Project => ({
10 id: "prj_1",
11 workspace: "acme",
12 slug: "web",
13 name: "web",
14 description: null,
15 source: { kind: "hosted", repoId: "repo_web", repo: { namespace: "acme", name: "web" }, rootDir: "", defaultBranch: "main" },
16 private: isPrivate,
17 archived: false,
18 primary: true,
19 createdBy: "ada",
20 createdAt: "2026-10-01T00:00:00Z",
21 updatedAt: "2026-10-01T00:00:00Z",
22});
23
24const person = (extra: Partial<User>): User => ({ id: "u", username: "u", kind: "user", verified: true, workspaces: [], ...extra }) as User;
25const collaborator = (role: "read" | "write" | "admin") => person({ grants: [{ repo_id: "repo_web", workspace: "acme", role }] });
26
27const allowed = (viewer: User | null, method: Method, isPrivate = true) => can(viewer, repoRef(project(isPrivate)), NEEDS[method]);
28
29test("a Read collaborator sees a project's deployments but cannot deploy or change them", () => {
30 const reader = collaborator("read");
31 for (const method of ["settings", "list", "get", "listDomains"] as const) assert.ok(allowed(reader, method), method);
Projects no longer depend on each other: the dependsOn relation, its settings page (old links redirect), the overview card, a pull request's Affects panel and preview stacks, reference variables and agents' notes on what a project uses are gone; the table is dropped in a later deploy32 for (const method of ["redeploy", "takeDown", "updateSettings", "addDomain"] as const) assert.ok(!allowed(reader, method), method);
The runner base keeps its old comment, so the pushed base image still matches its folder33 assert.equal(needs(NEEDS.redeploy), "Needs the Write role or higher.");
34});
35
36test("an outside collaborator with Write can deploy, but settings and domains need Admin", () => {
37 const writer = collaborator("write");
38 assert.ok(allowed(writer, "redeploy"));
39 assert.ok(allowed(writer, "takeDown"));
40 assert.ok(!allowed(writer, "updateSettings"));
41 assert.ok(!allowed(writer, "addDomain"));
42 assert.equal(needs(NEEDS.addDomain), "Needs the Admin role or higher.");
43 assert.ok(allowed(collaborator("admin"), "addDomain"));
44});
45
46test("members follow the workspace's base permission; owners manage everything", () => {
47 const member = person({ workspaces: [{ slug: "acme", role: "member" }] });
48 assert.ok(allowed(member, "redeploy"), "Write by default");
49 assert.ok(!allowed(member, "updateSettings"));
50 const none = person({ workspaces: [{ slug: "acme", role: "member", base_permission: "none" }] });
51 assert.equal(permission(none, repoRef(project(true))), null, "a private project is not found");
52 const owner = person({ workspaces: [{ slug: "acme", role: "owner" }] });
53 assert.ok(allowed(owner, "updateSettings"));
54});
55
56test("anyone can see a public project's deployments, and no more", () => {
57 assert.ok(allowed(null, "list", false));
58 assert.ok(!allowed(null, "redeploy", false));
59 assert.equal(permission(null, repoRef(project(true))), null);
60});
61
62test("a preview of g1t's change for someone is trusted as they are", async () => {
63 const { workOwner } = await import("../../../packages/contracts/src/work.ts");
64 const { trustedOutright } = await import("./access.ts");
65 const g1t: User = { id: "usr_g1t_agent", username: "g1t", kind: "agent", verified: false, workspaces: [] };
66 const syntaqx: User = { id: "usr_1", username: "syntaqx", kind: "user", verified: false, workspaces: [] };
67 // Made for syntaqx: their role decides, as when they were its author.
68 const made = workOwner({ author: g1t, requestedBy: syntaqx });
69 assert.equal(made.username, "syntaqx");
70 assert.equal(trustedOutright(made), false);
71 // g1t's own work, which nobody asked for, is g1t's.
72 assert.equal(trustedOutright(workOwner({ author: g1t, requestedBy: null })), true);
73 // Anyone's own pull request: they are asked about.
74 assert.equal(trustedOutright(workOwner({ author: syntaqx, requestedBy: null })), false);
75});

This file's history is long; its oldest lines are credited to the oldest commit read.