Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t.sh
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 sidebar asks billing whether it is on, not for the account, so no page waits on the card processor1import 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 sidebar asks billing whether it is on, not for the account, so no page waits on the card processor33 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.