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
105 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.

Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import type { AuditEntry } from "@g1t/contracts";
5
6import {
7 actorLabel,
8 exportName,
9 filterHref,
10 parseFilters,
11 retainedSince,
12 ruleLabel,
13 targetLabel,
14 toCsv,
15 toQuery,
16 visibilityFor,
17} from "./audit.ts";
18
19const entry: AuditEntry = {
20 id: "aud_1",
21 time: "2026-10-04T12:00:00.000Z",
22 actorKind: "agent",
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent23 actor: "g1t",
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily24 actorId: "usr_g1t_agent",
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent25 agent: "g1t",
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily26 onBehalfOf: "syntaqx",
27 runId: "run_1",
28 runKind: "implement",
29 credentialId: "tok_1",
30 action: "merge_pull_request",
31 surface: "mcp",
32 workspace: "acme",
33 repo: "acme/rocket",
34 number: 12,
35 gitRef: null,
36 path: null,
37 outcome: "denied",
38 rule: "never",
39 result: "forbidden",
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent40 message: 'g1t\'s token can never use merge_pull_request: "merging" is for people, too.',
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily41 requestId: "8c1f",
42};
43
44test("owners see everything, members their projects, others nothing", () => {
45 assert.deepEqual(visibilityFor("owner", "ana"), { kind: "all" });
46 assert.deepEqual(visibilityFor("member", "ana"), { kind: "projects", username: "ana" });
47 assert.equal(visibilityFor(null, "ana"), null);
48});
49
50test("filters are read from the address, and nonsense is dropped", () => {
51 const filters = parseFilters(
52 new URLSearchParams("actor=syntaqx&outcome=maybe&kind=agent&from=2026-10-01&to=yesterday&project=rocket"),
53 );
54 assert.equal(filters.actor, "syntaqx");
55 assert.equal(filters.outcome, "");
56 assert.equal(filters.kind, "agent");
57 assert.equal(filters.from, "2026-10-01");
58 assert.equal(filters.to, "");
59 const query = toQuery("acme", { kind: "all" }, { ...filters, to: "2026-10-04" }, 100);
60 assert.equal(query.repo, "acme/rocket");
61 assert.equal(query.since, "2026-10-01T00:00:00.000Z");
62 // The end day is inclusive.
63 assert.equal(query.until, "2026-10-05T00:00:00.000Z");
64 assert.equal(query.actorKind, "agent");
65 assert.equal(query.outcome, null);
66});
67
68test("links keep the other filters", () => {
69 const filters = parseFilters(new URLSearchParams("actor=ana&outcome=denied"));
70 assert.equal(filterHref("/acme/-/audit", filters, { before: "aud_9" }), "/acme/-/audit?actor=ana&outcome=denied&before=aud_9");
71 assert.equal(filterHref("/acme/-/audit", parseFilters(new URLSearchParams())), "/acme/-/audit");
72});
73
74test("an agent is shown with whom it acted for", () => {
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent75 assert.equal(actorLabel(entry), "g1t on behalf of syntaqx");
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily76 assert.equal(actorLabel({ actor: "ana", agent: null, onBehalfOf: null }), "ana");
77 assert.equal(targetLabel(entry), "acme/rocket#12");
78 assert.equal(targetLabel({ ...entry, number: null, gitRef: "refs/heads/fix" }), "acme/rocket refs/heads/fix");
79 assert.equal(ruleLabel("never"), "never allowed for agents");
80 assert.equal(ruleLabel("run:implement/tools"), "implement run tools");
81 assert.equal(ruleLabel("run:update/runner:push"), "update run runner (push)");
82});
83
84test("the CSV quotes what it must and keeps formulas as text", () => {
85 const csv = toCsv([entry, { ...entry, id: "aud_2", path: "=HYPERLINK(1)", message: null }]);
86 const lines = csv.trimEnd().split("\r\n");
87 assert.equal(lines.length, 3);
88 assert.ok(lines[0].startsWith("id,time,workspace,actorKind,actor"));
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent89 assert.ok(lines[1].includes('"g1t\'s token can never use merge_pull_request: ""merging"" is for people, too."'));
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily90 assert.ok(lines[2].includes("'=HYPERLINK(1)"));
91 assert.equal(exportName("acme", "csv", new Date("2026-10-04T23:00:00Z")), "acme-audit-2026-10-04.csv");
92});
93
94test("the log reads back only as far as the plan keeps it", () => {
95 const now = Date.parse("2026-10-31T00:00:00.000Z");
Audit logs are kept by plan: a week on free, 90 days on the plan, and what staff set for an account in sudo96 // 90 days on the plan, 7 free.
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily97 assert.equal(retainedSince(null, 90, now), "2026-08-02T00:00:00.000Z");
Audit logs are kept by plan: a week on free, 90 days on the plan, and what staff set for an account in sudo98 assert.equal(retainedSince(null, 7, now), "2026-10-24T00:00:00.000Z");
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily99 assert.equal(retainedSince(null, 30, now), "2026-10-01T00:00:00.000Z");
100 assert.equal(retainedSince("2026-01-01T00:00:00.000Z", 30, now), "2026-10-01T00:00:00.000Z");
101 // A later start than the window is kept.
102 assert.equal(retainedSince("2026-10-20T00:00:00.000Z", 30, now), "2026-10-20T00:00:00.000Z");
103 // A longer window, where one is set.
104 assert.equal(retainedSince("2026-01-01T00:00:00.000Z", 365, now), "2026-01-01T00:00:00.000Z");
105});

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