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

Flagon, Inc.'s workspace runs comped and can use hosted agents, like g1t's own1//! Staff-only views of workspaces, for sudo.g1t.sh.
2//!
3//! These methods take no viewer and check no membership. Only sudo calls
4//! them, over its service binding, once it has verified a Cloudflare Access
5//! sign-in against its staff list; nothing a customer can reach forwards to
6//! them. They read, and never change, anything.
7//!
8//! Every workspace is listed: there is one kind, and a person's own space
9//! is simply a workspace with one member. A user with no workspace has
10//! nothing to list, as nothing can exist outside one.
11
12use std::collections::HashMap;
13
14use g1t_contracts::Role;
15use g1t_contracts::identity::*;
16use serde::Deserialize;
17use worker::Result;
18
19use crate::Identity;
20
21#[derive(Deserialize)]
22struct ListRow {
23 id: String,
24 slug: String,
25 name: String,
26 created_at: String,
27 member_count: u32,
28}
29
30#[derive(Deserialize)]
31struct OwnerRow {
32 workspace_id: String,
33 username: String,
34 email: Option<String>,
35}
36
37#[derive(Deserialize)]
38struct DetailRow {
39 id: String,
40 slug: String,
41 name: String,
42 description: Option<String>,
43 created_at: String,
Packages, with a container registry on g1t.sh; workspaces deleted whole and kept 30 days; Members for every member44 #[serde(default)]
45 protected: u8,
Flagon, Inc.'s workspace runs comped and can use hosted agents, like g1t's own46}
47
48#[derive(Deserialize)]
49struct MemberRow {
50 username: String,
51 email: Option<String>,
52 role: Role,
53 joined: String,
54}
55
56/// A `LIKE` pattern matching `query` anywhere, lowercased, with `%`, `_`
57/// and the escape character itself taken literally. None for a blank query.
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look58pub(crate) fn like_pattern(query: Option<&str>) -> Option<String> {
Flagon, Inc.'s workspace runs comped and can use hosted agents, like g1t's own59 let query = query.map(str::trim).filter(|q| !q.is_empty())?;
60 let mut pattern = String::from("%");
61 for c in query.to_lowercase().chars().take(100) {
62 if matches!(c, '%' | '_' | '\\') {
63 pattern.push('\\');
64 }
65 pattern.push(c);
66 }
67 pattern.push('%');
68 Some(pattern)
69}
70
71/// The workspaces, in their order, each with its owners.
72fn with_owners(rows: Vec<ListRow>, owners: Vec<OwnerRow>) -> Vec<AdminWorkspace> {
73 let mut by_workspace: HashMap<String, Vec<AdminOwner>> = HashMap::new();
74 for owner in owners {
75 by_workspace.entry(owner.workspace_id).or_default().push(AdminOwner {
76 username: owner.username,
77 email: owner.email,
78 });
79 }
80 rows.into_iter()
81 .map(|row| AdminWorkspace {
82 owners: by_workspace.remove(&row.id).unwrap_or_default(),
83 slug: row.slug,
84 name: row.name,
85 created_at: row.created_at,
86 member_count: row.member_count,
87 })
88 .collect()
89}
90
91impl Identity {
92 /// The workspaces staff can see, newest first. Staff only: see the
93 /// module's note.
94 /// Emails each owner of the workspace with a confirmed address. Only
95 /// other services call this; the link must stay on g1t.sh, so a notice
96 /// can never point owners anywhere else.
97 pub async fn notify_owners(&self, a: NotifyOwnersArgs) -> Result<u32> {
98 if !a.link.starts_with("https://g1t.sh/") {
99 return Ok(0);
100 }
101 #[derive(Deserialize)]
102 struct Owner {
103 email: Option<String>,
104 }
105 let owners = self
106 .db
107 .prepare(
108 "SELECT u.email FROM workspace_members m
109 JOIN users u ON u.id = m.user_id
110 JOIN workspaces w ON w.id = m.workspace_id
Packages, with a container registry on g1t.sh; workspaces deleted whole and kept 30 days; Members for every member111 WHERE w.slug = ? AND w.deleted_at IS NULL AND m.role = 'owner' AND u.email_verified_at IS NOT NULL",
Flagon, Inc.'s workspace runs comped and can use hosted agents, like g1t's own112 )
113 .bind(&[a.workspace.to_lowercase().into()])?
114 .all()
115 .await?
116 .results::<Owner>()?;
117 let mut sent = 0;
118 for email in owners.into_iter().filter_map(|owner| owner.email) {
119 match crate::email::send_link(&self.env, &email, &a.subject, &a.intro, &a.action, &a.link, &a.footer).await {
120 Ok(()) => sent += 1,
121 Err(error) => worker::console_error!("could not email an owner of {}: {error}", a.workspace),
122 }
123 }
124 Ok(sent)
125 }
126
127 pub async fn admin_workspaces(&self, a: AdminWorkspacesArgs) -> Result<Vec<AdminWorkspace>> {
128 let pattern = like_pattern(a.query.as_deref());
129 // The same filter picks the workspaces and, below, their owners.
Packages, with a container registry on g1t.sh; workspaces deleted whole and kept 30 days; Members for every member130 // Deleted ones are listed apart (`admin_deleted_workspaces`).
Flagon, Inc.'s workspace runs comped and can use hosted agents, like g1t's own131 let filter = if pattern.is_some() {
Packages, with a container registry on g1t.sh; workspaces deleted whole and kept 30 days; Members for every member132 "WHERE w.deleted_at IS NULL AND (w.slug LIKE ?1 ESCAPE '\\' OR lower(w.name) LIKE ?1 ESCAPE '\\'
Flagon, Inc.'s workspace runs comped and can use hosted agents, like g1t's own133 OR EXISTS (SELECT 1 FROM workspace_members om JOIN users ou ON ou.id = om.user_id
134 WHERE om.workspace_id = w.id AND om.role = 'owner'
Packages, with a container registry on g1t.sh; workspaces deleted whole and kept 30 days; Members for every member135 AND (lower(ou.username) LIKE ?1 ESCAPE '\\' OR lower(ou.email) LIKE ?1 ESCAPE '\\')))"
Flagon, Inc.'s workspace runs comped and can use hosted agents, like g1t's own136 } else {
Packages, with a container registry on g1t.sh; workspaces deleted whole and kept 30 days; Members for every member137 "WHERE w.deleted_at IS NULL"
Flagon, Inc.'s workspace runs comped and can use hosted agents, like g1t's own138 };
139 let chosen = format!(
140 "SELECT w.id FROM workspaces w {filter}
141 ORDER BY w.created_at DESC, w.slug LIMIT {ADMIN_WORKSPACES_LIMIT}"
142 );
143 let binds: Vec<worker::wasm_bindgen::JsValue> = pattern.into_iter().map(Into::into).collect();
144 let rows = self
145 .db
146 .prepare(format!(
147 "SELECT w.id, w.slug, w.name, w.created_at,
148 (SELECT count(*) FROM workspace_members m WHERE m.workspace_id = w.id) AS member_count
149 FROM workspaces w WHERE w.id IN ({chosen})
150 ORDER BY w.created_at DESC, w.slug"
151 ))
152 .bind(&binds)?
153 .all()
154 .await?
155 .results::<ListRow>()?;
156 let owners = self
157 .db
158 .prepare(format!(
159 "SELECT m.workspace_id, u.username, u.email FROM workspace_members m
160 JOIN users u ON u.id = m.user_id
161 WHERE m.role = 'owner' AND m.workspace_id IN ({chosen})
162 ORDER BY m.created_at, u.username"
163 ))
164 .bind(&binds)?
165 .all()
166 .await?
167 .results::<OwnerRow>()?;
168 Ok(with_owners(rows, owners))
169 }
170
171 /// One workspace with every member, or None. Staff only: see the
172 /// module's note.
173 pub async fn admin_workspace(&self, a: SlugArgs) -> Result<Option<AdminWorkspaceDetail>> {
174 let Some(row) = self
175 .db
Packages, with a container registry on g1t.sh; workspaces deleted whole and kept 30 days; Members for every member176 .prepare("SELECT id, slug, name, description, created_at, protected FROM workspaces WHERE slug = ?")
Flagon, Inc.'s workspace runs comped and can use hosted agents, like g1t's own177 .bind(&[a.slug.trim().to_lowercase().into()])?
178 .first::<DetailRow>(None)
179 .await?
180 else {
181 return Ok(None);
182 };
183 let members = self
184 .db
185 .prepare(
186 "SELECT u.username, u.email, m.role, m.created_at AS joined FROM workspace_members m
187 JOIN users u ON u.id = m.user_id
188 WHERE m.workspace_id = ?
189 ORDER BY m.role DESC, u.username",
190 )
191 .bind(&[row.id.as_str().into()])?
192 .all()
193 .await?
194 .results::<MemberRow>()?
195 .into_iter()
196 .map(|m| AdminMember {
197 username: m.username,
198 email: m.email,
199 role: m.role,
200 joined: m.joined,
201 })
202 .collect();
Packages, with a container registry on g1t.sh; workspaces deleted whole and kept 30 days; Members for every member203 let protected = self.is_protected(&row.id, &row.slug, row.protected != 0).await?;
Flagon, Inc.'s workspace runs comped and can use hosted agents, like g1t's own204 Ok(Some(AdminWorkspaceDetail {
Packages, with a container registry on g1t.sh; workspaces deleted whole and kept 30 days; Members for every member205 protected,
Flagon, Inc.'s workspace runs comped and can use hosted agents, like g1t's own206 slug: row.slug,
207 name: row.name,
208 description: row.description,
209 created_at: row.created_at,
210 members,
211 }))
212 }
213}
214
215#[cfg(test)]
216mod tests {
217 use super::*;
218
219 #[test]
220 fn a_blank_query_matches_everything() {
221 assert_eq!(like_pattern(None), None);
222 assert_eq!(like_pattern(Some(" ")), None);
223 }
224
225 #[test]
226 fn a_query_is_matched_literally_anywhere() {
227 assert_eq!(like_pattern(Some(" Acme ")).as_deref(), Some("%acme%"));
228 assert_eq!(like_pattern(Some("50%_off\\")).as_deref(), Some("%50\\%\\_off\\\\%"));
229 }
230
231 #[test]
232 fn owners_go_to_their_workspaces_in_order() {
233 let row = |id: &str, slug: &str| ListRow {
234 id: id.into(),
235 slug: slug.into(),
236 name: slug.into(),
237 created_at: "2026-10-04T00:00:00Z".into(),
238 member_count: 2,
239 };
240 let owner = |workspace_id: &str, username: &str| OwnerRow {
241 workspace_id: workspace_id.into(),
242 username: username.into(),
243 email: Some(format!("{username}@example.com")),
244 };
245 let listed = with_owners(
246 vec![row("wsp_2", "newer"), row("wsp_1", "older"), row("wsp_3", "orphan")],
247 vec![owner("wsp_1", "ada"), owner("wsp_2", "bob"), owner("wsp_1", "cy")],
248 );
249 let slugs: Vec<_> = listed.iter().map(|w| w.slug.as_str()).collect();
250 assert_eq!(slugs, ["newer", "older", "orphan"]);
251 let owners = |i: usize| listed[i].owners.iter().map(|o| o.username.as_str()).collect::<Vec<_>>();
252 assert_eq!(owners(0), ["bob"]);
253 assert_eq!(owners(1), ["ada", "cy"]);
254 assert!(owners(2).is_empty());
255 assert_eq!(listed[1].owners[0].email.as_deref(), Some("ada@example.com"));
256 }
257}

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