Skip to content
151 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.

Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar1import { FileSearch } from "lucide-react";
2import { Form, useNavigation, useSearchParams } from "react-router";
3
4import type { AlertState, Severity } from "@g1t/contracts";
5
6import type { Route } from "./+types/security-code";
7import { page } from "../../lib/meta";
8import { StateFilter } from "../../components/security";
9import { ActivationPrompt, CARD, CodeAlertItem, FilterSelect, LIST, SectionHeader } from "../../components/security-suite";
10import { TimeAgo } from "../../components/ui";
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.11import { Button } from "../../components/ui/button";
12import { Card } from "../../components/ui/card";
13import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "../../components/ui/table";
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar14import { securitySuite } from "../../lib/services.server";
Merge main (membership, two-factor, GitHub repo roles) into tokens15import { getViewer, managesSecurity, requireUser, unwrap } from "../../lib/session.server";
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar16import { requireInsider } from "../../lib/access.server";
Pricing says it plainly: models at the provider's price, the agent rate for what g1t runs around every model call (the gateway, secrets, routing, context and pass-through to your own provider, so your own keys too), everything else at cost plus 20%, your own runners free, no seats; Security and quality comes with the plan with no separate fee, and live activations end. Each agent has an effort setting, Auto to Max, with what a typical task has cost at each level, and Spend's Spend less, keep quality suggests a lower level only when the agent's own past work shows quality held, to apply or dismiss. The pricing, spend and agents guides say how.17import { planPrice } from "../../lib/security-suite.server";
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar18import { codeFilters, countStates, keepCode } from "../../lib/security-suite";
19
20export function meta({ params, ...args }: Route.MetaArgs) {
21 return page(args, { title: `Code scanning · ${params.owner}/${params.repo} · g1t` });
22}
23
24export async function loader({ params, context, request }: Route.LoaderArgs) {
25 const viewer = getViewer(context) ?? requireUser(context, request);
Merge main (membership, two-factor, GitHub repo roles) into tokens26 const { access } = await requireInsider(context, params, "security_alerts");
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar27 const repo = { namespace: params.owner, name: params.repo };
Pricing says it plainly: models at the provider's price, the agent rate for what g1t runs around every model call (the gateway, secrets, routing, context and pass-through to your own provider, so your own keys too), everything else at cost plus 20%, your own runners free, no seats; Security and quality comes with the plan with no separate fee, and live activations end. Each agent has an effort setting, Auto to Max, with what a typical task has cost at each level, and Spend's Spend less, keep quality suggests a lower level only when the agent's own past work shows quality held, to apply or dismiss. The pricing, spend and agents guides say how.28 const [scanning, price] = await Promise.all([securitySuite.codeScanning(repo, viewer), planPrice(params.owner, viewer)]);
Merge main (membership, two-factor, GitHub repo roles) into tokens29 return { scanning: unwrap(scanning), price, can: access.can, owner: managesSecurity(viewer, params.owner) };
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar30}
31
32const SEVERITY_OPTIONS: [string, string][] = [
33 ["all", "Any severity"],
34 ["critical", "Critical"],
35 ["high", "High"],
36 ["medium", "Medium"],
37 ["low", "Low"],
38];
39
40export default function CodeScanning({ loaderData, params }: Route.ComponentProps) {
41 const { scanning, price, can, owner } = loaderData;
42 const base = `/${params.owner}/${params.repo}`;
43 const [search, setSearch] = useSearchParams();
44 const navigation = useNavigation();
45 const filters = codeFilters(search);
46 const tools = [...new Set(scanning.alerts.map((alert) => alert.tool))].sort();
47 const counts = countStates(scanning.alerts.filter((alert) => keepCode(alert, { ...filters, state: alert.state })));
48 const shown = scanning.alerts.filter((alert) => keepCode(alert, filters));
49 const set = (key: string, value: string | null) => {
50 const next = new URLSearchParams(search);
51 if (value) next.set(key, value);
52 else next.delete(key);
53 setSearch(next, { replace: true, preventScrollReset: true });
54 };
55 const empty = scanning.alerts.length === 0 && scanning.analyses.length === 0;
56 const settingUp = navigation.state !== "idle" && navigation.formAction?.endsWith("/code-scanning/setup");
57 return (
58 <div className="max-w-5xl space-y-8">
59 <SectionHeader
60 title="Code scanning"
61 about="Results from your static analysis tools, uploaded as SARIF. On the default branch each problem is an alert, fixed when a later analysis no longer reports it. On a pull request, new results on the lines it changes become review comments and the Code scanning check."
62 actions={
63 scanning.entitled && can.manage_settings && !scanning.configured ? (
64 <Form method="post" action={`${base}/security/code-scanning/setup`}>
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.65 <Button type="submit" disabled={settingUp}>
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar66 {settingUp ? "Opening a pull request…" : "Set up code scanning"}
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.67 </Button>
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar68 </Form>
69 ) : null
70 }
71 />
72 {!scanning.entitled ? (
73 <ActivationPrompt workspace={params.owner} feature="Code scanning" monthlyCents={price} isOwner={owner} />
74 ) : empty ? (
75 <div className={`${CARD} px-6 py-10 text-center`}>
76 <FileSearch size={22} className="mx-auto text-accent" />
77 <p className="mt-2 font-medium">No analyses yet</p>
78 <p className="mx-auto mt-1 max-w-xl text-sm text-muted">
79 {scanning.configured
80 ? "The code scanning workflow is on the default branch; its first run's results show here."
81 : "Set up code scanning to open a pull request adding a workflow that scans each language the repository has (Bandit, gosec, ESLint, Clippy) and uploads the results, or upload SARIF from any tool with POST /repos/{owner}/{name}/code-scanning/sarifs."}
82 </p>
83 </div>
84 ) : (
85 <section className="space-y-3">
86 <div className="flex flex-wrap items-end justify-between gap-3">
87 <StateFilter counts={counts} value={filters.state} onChange={(state: AlertState) => set("state", state === "open" ? null : state)} />
88 <div className="flex flex-wrap gap-2">
89 <FilterSelect label="Severity" value={filters.severity ?? "all"} options={SEVERITY_OPTIONS} onChange={(value) => set("severity", value === "all" ? null : (value as Severity))} />
90 <FilterSelect label="Tool" value={filters.tool ?? "all"} options={[["all", "Every tool"], ...tools.map((tool): [string, string] => [tool, tool])]} onChange={(value) => set("tool", value === "all" ? null : value)} />
91 </div>
92 </div>
93 {shown.length === 0 ? (
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.94 <Card asChild tone="plain" className="border-dashed px-4 py-6 text-sm text-muted">
95 <p>No {filters.state} alerts match.</p>
96 </Card>
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar97 ) : (
98 <ul className={LIST}>
99 {shown.map((alert) => (
100 <CodeAlertItem key={alert.id} alert={alert} base={base} />
101 ))}
102 </ul>
103 )}
104 </section>
105 )}
106 {scanning.analyses.length > 0 && (
107 <section>
108 <h3 className="text-base font-semibold tracking-tight">Recent analyses</h3>
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.109 <div className={`${CARD} mt-2`}>
110 <Table className="min-w-[36rem]">
111 <TableHeader>
112 <TableRow>
113 <TableHead className="px-4">Tool</TableHead>
114 <TableHead>Ref</TableHead>
115 <TableHead>Commit</TableHead>
116 <TableHead className="text-right">Results</TableHead>
117 <TableHead className="text-right">New</TableHead>
118 <TableHead className="text-right">Fixed</TableHead>
119 <TableHead>When</TableHead>
120 </TableRow>
121 </TableHeader>
122 <TableBody className="tabular-nums">
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar123 {scanning.analyses.slice(0, 15).map((analysis) => (
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.124 <TableRow key={analysis.id}>
125 <TableCell className="px-4">{analysis.tool}</TableCell>
126 <TableCell className="font-mono text-xs">
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar127 {analysis.pull != null ? (
128 <a href={`${base}/security/pulls/${analysis.pull}`} className="hover:underline">
129 #{analysis.pull}
130 </a>
131 ) : (
132 analysis.gitRef.replace("refs/heads/", "")
133 )}
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.134 </TableCell>
135 <TableCell className="font-mono text-xs">{analysis.commitSha.slice(0, 7)}</TableCell>
136 <TableCell className="text-right">{analysis.results}</TableCell>
137 <TableCell className="text-right">{analysis.newAlerts}</TableCell>
138 <TableCell className="text-right">{analysis.fixedAlerts}</TableCell>
139 <TableCell className="text-xs text-muted">
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar140 <TimeAgo at={analysis.createdAt} />
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.141 </TableCell>
142 </TableRow>
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar143 ))}
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.144 </TableBody>
145 </Table>
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar146 </div>
147 </section>
148 )}
149 </div>
150 );
151}

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