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.

Put the stylesheet at the top of the head, before React Router's preloads1import 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);
Put the stylesheet at the top of the head, before React Router's preloads33 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});
g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights61
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.