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

Icons are cached at the edge1//! Types and service interfaces shared by every g1t service.
2//!
3//! Each service has a module here holding the data it exchanges and the
4//! arguments of each of its methods. Services and their callers depend on
5//! this crate, never on each other's code.
6
Merge branch 'main' into worktree-agent-a69aeabc4b0deeb977pub mod about;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look8pub mod access;
Security tells people the way they can live with. Each scan publishes one summary event per alert type (secret_scanning_alert.summary, code_scanning_alert.summary, vulnerability_alert.summary: what it opened, by severity, what it fixed, what is open now, the worst new alert and the newest one's title, with the owners and security managers to tell) beside the per-alert events webhooks keep, so the inbox holds one thread per repository and alert type that the next scan brings up to date instead of one item per finding, and the ids are capped at 200 while the counts are not. Critical and high alerts and a refused push reach the inbox at once (and toast like a mention, as the new security notification kind); medium and low wait for each person's security digest, one inbox item and email per workspace, daily or weekly as they choose in their notification settings, at once, or never; a scan that opened nothing refreshes the thread quietly ("2 of 3 fixed") and marks it done when nothing is left open; and security alerts are emailed by default. A repository can turn alerts for secrets found in its history off while push protection stays on. Reporting arrives: security advisories (G1TSA ids, drafts published and withdrawn by Admins and security managers, visible to anyone who can see the repository once published) and private vulnerability reporting (a repository setting; anyone who can see it may report, signed out with an email on a public one, five a day each, and the owners and security managers are told at once), each with its RPC methods, REST routes under /repos/{owner}/{name}/security/advisories and /security/reports, MCP actions, scopes and reference examples.9pub mod advisories;
Merge account deletion: soft delete for 30 days, staff restore and purge, ghost for what remains (identity 0037)10pub mod account_deletion;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look11pub mod accounts;
Icons are cached at the edge12pub mod actions;
Agents and memory, checks and conflicts, profiles, slug renames, custom domains13pub mod agents;
Agents get guardrails, run credentials, an audit log, a context hub, repository instructions and mentions; security upkeep; snake_case API14pub mod audit;
Merge branch 'worktree-agent-ac5b181a013e54348'15pub mod backups;
Icons are cached at the edge16pub mod billing;
Agents get guardrails, run credentials, an audit log, a context hub, repository instructions and mentions; security upkeep; snake_case API17pub mod capture;
Merge checks: statuses and check runs on every commit18pub mod checks;
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar19pub mod codeowners;
Agents get guardrails, run credentials, an audit log, a context hub, repository instructions and mentions; security upkeep; snake_case API20pub mod credentials;
Artifacts contracts: folios, their four kinds, dashboard datasets, folio events and the artifacts scopes are typed and validated the same in TypeScript and Rust, with nothing using them yet21pub mod datasets;
Merge branch 'worktree-agent-a5a5de74d8863d554' into worktree-agent-a16631325aecf58ca22pub mod deploy_keys;
Icons are cached at the edge23pub mod events;
Artifacts contracts: folios, their four kinds, dashboard datasets, folio events and the artifacts scopes are typed and validated the same in TypeScript and Rust, with nothing using them yet24pub mod folios;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look25pub mod github;
Agents get guardrails, run credentials, an audit log, a context hub, repository instructions and mentions; security upkeep; snake_case API26pub mod guardrails;
Icons are cached at the edge27pub mod identity;
Inbox: the events service tells people what needs them as events arrive28pub mod inbox;
Icons are cached at the edge29pub mod integrations;
Merge main (membership, two-factor, GitHub repo roles) into tokens30pub mod members;
Merge branch 'mirroring' into artifacts-mode31pub mod mirrors;
Icons are cached at the edge32mod ids;
33mod names;
34mod outcome;
Packages, with a container registry on g1t.sh; workspaces deleted whole and kept 30 days; Members for every member35pub mod packages;
People and teams are front and centre: one directory of people and agents with presence, local time, titles, teams and what each owns; profiles with manager and reports and the agents they work with; an org chart with each team's agents beside the person who leads it; and teams of any mix, with a lead, a channel, a budget agents keep to and the agents on them. Every agent is told its teams each turn (who leads, who owns what, who's around and who to page), and the team page shows exactly what. Member management is Members and invites; the people and teams guide says how.36pub mod people;
Icons are cached at the edge37pub mod projects;
38pub mod repos;
Merge rulesets: branch and tag rules, agent-first, enforced on push and merge39pub mod rules;
Fast pages, required checks on the branch, self-hosted runners, honest incidents40pub mod runners;
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step41pub mod scopes;
Search across all of g1t, Explore, and a command palette42pub mod search;
Agents get guardrails, run credentials, an audit log, a context hub, repository instructions and mentions; security upkeep; snake_case API43pub mod security;
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar44pub mod teams;
45pub mod security_suite;
Merge branch 'worktree-agent-ad8a36dfcd4176015' into spend-guardrails46pub mod subscribers;
Icons are cached at the edge47pub mod time;
Fine-grained personal tokens, workspace token rules and approvals in identity48pub mod tokens;
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar49pub mod updates;
Icons are cached at the edge50pub mod webhooks;
51pub mod work;
52
Home says what people did as well as what agents did. Since you were last here now has a People column and an Agents column: who pushed how many commits to which projects, pull requests opened, merged and reviewed, issues opened and closed, docs edited, messages sent and deploys that went out, each line a link to where those are listed, with the agents' acceptance (first time, after review, didn't finish) kept as a row of their column; the sentence under the heading sums it up honestly, and says when a part of g1t could not be read, or that the span was quiet. Landed counts merged pull requests, commits pushed straight to a default branch, production deploys that went live, releases and packages, newest first; Running now adds workflow runs. Behind it, the events service answers an activity digest over a span in one round trip from its existing indexes, every push now records how many commits it carried, and chat counts the messages sent in the conversations you can read. The Home guide defines every line, and says how this scales.53pub use ids::{id_floor, new_id};
Merge branch 'worktree-agent-a8385d293d42c913a'54pub use names::{
One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers55 Username, aliasable_name, claimable_namespace, claimable_username, is_namespace_shaped, is_reserved_name, is_route_name,
56 is_valid_namespace, is_valid_repo_name,
Merge branch 'worktree-agent-a8385d293d42c913a'57};
Icons are cached at the edge58pub use outcome::{Failure, FailureCode, Outcome};
59
60use serde::{Deserialize, Serialize};
61
Merge main (membership, two-factor, GitHub repo roles) into tokens62/// What a member may do in a workspace. A member may also hold
63/// [`members::OrgRole`]s, which add to it.
Icons are cached at the edge64#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
65#[serde(rename_all = "lowercase")]
66pub enum Role {
Merge main (membership, two-factor, GitHub repo roles) into tokens67 /// Everything: Admin on every repository, the workspace's members,
68 /// settings, billing and security.
Icons are cached at the edge69 Owner,
Merge main (membership, two-factor, GitHub repo roles) into tokens70 /// The workspace's base permission on each repository, and what its
71 /// member privileges allow (see [`members::MemberPrivileges`]).
Icons are cached at the edge72 Member,
73}
74
Merge main (membership, two-factor, GitHub repo roles) into tokens75pub use members::{MemberPrivileges, OrgRole};
76
Icons are cached at the edge77/// One workspace a user belongs to.
78#[derive(Clone, Debug, Serialize, Deserialize)]
79pub struct Membership {
80 /// The workspace's name in URLs: `g1t.sh/<slug>`.
81 pub slug: String,
82 pub role: Role,
83 /// The workspace's display name, for showing it to people. Set when a
84 /// user is resolved from credentials; absent on principals made up by
85 /// a service.
86 #[serde(default, skip_serializing_if = "Option::is_none")]
87 pub name: Option<String>,
88 /// The workspace's uploaded icon: the SHA-256 of its bytes, served at
89 /// `/avatars/<avatar>`. Absent means the generated letter avatar.
90 #[serde(default, skip_serializing_if = "Option::is_none")]
91 pub avatar: Option<String>,
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look92 /// What a member gets on each of the workspace's repositories: the
93 /// workspace's base permission. Set when a user is resolved from
94 /// credentials; absent means the default, Write. Owners have Admin
95 /// whatever it says. See [`access`].
96 #[serde(default, skip_serializing_if = "Option::is_none")]
97 pub base_permission: Option<access::BasePermission>,
Merge branch 'worktree-agent-ad7c6d88d93adc817'98 /// Who may create the workspace's teams. Set when a user is resolved
99 /// from credentials; absent means the default, any member. See
100 /// [`teams::TeamCreation`].
101 #[serde(default, skip_serializing_if = "Option::is_none")]
102 pub team_creation: Option<teams::TeamCreation>,
Merge main (membership, two-factor, GitHub repo roles) into tokens103 /// The roles the member holds besides `role`: billing manager,
104 /// security manager. Set when a user is resolved from credentials.
105 #[serde(default, skip_serializing_if = "Vec::is_empty")]
106 pub org_roles: Vec<OrgRole>,
107 /// What the workspace lets members (and repository admins) do. Set
108 /// when a user is resolved from credentials; absent means the
109 /// defaults. See [`members::MemberPrivileges`].
110 #[serde(default, skip_serializing_if = "Option::is_none")]
111 pub privileges: Option<MemberPrivileges>,
Icons are cached at the edge112}
113
114impl Membership {
115 /// A plain member of `slug`, as services act inside one workspace.
116 pub fn member(slug: impl Into<String>) -> Self {
117 Membership {
118 slug: slug.into(),
119 role: Role::Member,
120 name: None,
121 avatar: None,
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look122 base_permission: None,
Merge branch 'worktree-agent-ad7c6d88d93adc817'123 team_creation: None,
Merge main (membership, two-factor, GitHub repo roles) into tokens124 org_roles: Vec::new(),
125 privileges: None,
Icons are cached at the edge126 }
127 }
Merge main (membership, two-factor, GitHub repo roles) into tokens128
129 /// Whether the member holds `role` besides owner or member.
130 pub fn has(&self, role: OrgRole) -> bool {
131 self.org_roles.contains(&role)
132 }
Icons are cached at the edge133}
134
135/// What a set of credentials resolved to.
136#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
137#[serde(rename_all = "lowercase")]
138pub enum PrincipalKind {
139 /// A person's account.
140 #[default]
141 User,
142 /// A workspace, acting through one of its own access tokens. Its `id`
143 /// is the workspace's, its `username` the workspace's slug, and it is a
144 /// member of that workspace and no other.
145 Workspace,
146 /// A g1t agent at work in a sandbox, acting through a token that lives
147 /// as long as its run and can do only what that token's scope lists, in
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent148 /// one repository. Its `username` is `g1t`.
Icons are cached at the edge149 Agent,
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily150 /// g1t itself: the platform acting on its own, as when it opens a
151 /// pull request to upgrade a vulnerable dependency or merges from the
152 /// queue. Never resolved from credentials: only services make one,
153 /// with [`User::system`]. Its `username` is `g1t`, which nobody can
154 /// register.
155 System,
156}
157
158/// g1t's own identity, as [`PrincipalKind::System`] work is recorded.
159pub mod system {
160 /// Its id wherever an author or actor id is stored.
161 pub const ID: &str = "g1t";
162 /// Its name, shown as the author of what it does.
163 pub const USERNAME: &str = "g1t";
164 /// The address on the commits it makes, which no mailbox receives.
165 pub const EMAIL: &str = "g1t@users.noreply.g1t.sh";
166 /// Ids that earlier versions stored for g1t's own actions, such as a
167 /// merge its settings made. Read as g1t too.
168 pub const LEGACY_IDS: [&str; 3] = ["g1t_policy", "svc_runner", "g1t_runner"];
169
170 /// Whether `id` is g1t's own.
171 pub fn is_system_id(id: &str) -> bool {
172 id == ID || LEGACY_IDS.contains(&id)
173 }
Icons are cached at the edge174}
175
176#[derive(Clone, Debug, Default, Serialize, Deserialize)]
177pub struct User {
178 pub id: String,
One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers179 /// Lowercased: what the person is found, linked and mentioned by.
Icons are cached at the edge180 pub username: String,
One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers181 /// The username as its owner wrote it (`Ana`), when that differs from
182 /// `username`: what pages show. Set on the signed-in person and on
183 /// people looked up by name; absent elsewhere, where `username` is shown.
184 #[serde(default, skip_serializing_if = "Option::is_none")]
185 pub display_username: Option<String>,
Icons are cached at the edge186 #[serde(default)]
187 pub kind: PrincipalKind,
188 /// Whether the account's email address has been confirmed. Unverified
189 /// accounts can sign in but cannot create or change anything.
190 #[serde(default)]
191 pub verified: bool,
192 /// The workspaces this user belongs to. Filled in when a user is
193 /// resolved from credentials, so any service can authorize from it.
194 #[serde(default)]
195 pub workspaces: Vec<Membership>,
196 /// The person's uploaded avatar: the SHA-256 of its bytes, served at
197 /// `/avatars/<avatar>`. Absent means the generated letter avatar.
198 #[serde(default, skip_serializing_if = "Option::is_none")]
199 pub avatar: Option<String>,
Agents get guardrails, run credentials, an audit log, a context hub, repository instructions and mentions; security upkeep; snake_case API200 /// Set on an agent resolved from its token: who it acts for, with which
201 /// credential, and what it may do. See [`credentials`].
202 #[serde(default, skip_serializing_if = "Option::is_none")]
203 pub acting: Option<Box<credentials::Acting>>,
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look204 /// The repositories this user has been given a role on directly,
205 /// whether or not they belong to its workspace. Filled in with
206 /// `workspaces`; see [`access`].
207 #[serde(default, skip_serializing_if = "Vec::is_empty")]
208 pub grants: Vec<access::RepoGrant>,
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step209 /// Set on a user resolved from an access token: its scopes and the
210 /// workspaces or repositories it is limited to. Absent on a signed-in
211 /// session and on an agent (whose `acting` scope applies instead).
212 /// See [`scopes`].
213 #[serde(default, skip_serializing_if = "Option::is_none")]
214 pub token: Option<Box<scopes::TokenAccess>>,
Merge main (membership, two-factor, GitHub repo roles) into tokens215 /// The workspaces this person belongs to but cannot use until they
216 /// meet its policy, such as turning on two-factor authentication.
217 /// They are left out of `workspaces` and `grants` meanwhile. Set when
218 /// a person is resolved from a session.
219 #[serde(default, skip_serializing_if = "Vec::is_empty")]
220 pub held: Vec<members::PolicyHold>,
Icons are cached at the edge221}
222
223impl User {
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily224 /// g1t itself, acting in `workspace`: what the platform's own work,
225 /// such as security updates, is done and recorded as.
226 pub fn system(workspace: &str) -> User {
227 User {
228 id: system::ID.to_owned(),
229 username: system::USERNAME.to_owned(),
230 kind: PrincipalKind::System,
231 verified: true,
232 workspaces: vec![Membership::member(workspace.to_lowercase())],
233 ..User::default()
234 }
235 }
236
237 /// Whether this is g1t itself.
238 pub fn is_system(&self) -> bool {
239 self.kind == PrincipalKind::System
240 }
241
Merge email confirmation gate: a code and a link, nothing until confirmed (identity 0036)242 /// Whether this is a person whose account has not confirmed its email
243 /// address. Such an account can only confirm it (or change it, or sign
244 /// out): the site, the API, MCP and git refuse it everything else
245 /// ([`accounts::confirm_email_first`]).
246 pub fn awaits_confirmation(&self) -> bool {
247 self.kind == PrincipalKind::User && !self.verified
248 }
249
Icons are cached at the edge250 pub fn role_in(&self, slug: &str) -> Option<Role> {
251 self.workspaces
252 .iter()
253 .find(|membership| membership.slug == slug)
254 .map(|membership| membership.role)
255 }
256
257 pub fn is_member(&self, slug: &str) -> bool {
258 self.role_in(slug).is_some()
259 }
Merge main (membership, two-factor, GitHub repo roles) into tokens260
261 /// The membership in `slug`, if any.
262 pub fn membership(&self, slug: &str) -> Option<&Membership> {
263 self.workspaces.iter().find(|membership| membership.slug.eq_ignore_ascii_case(slug))
264 }
265
266 /// Whether this is a person who owns `slug`, or holds `role` in it.
267 pub fn owns_or_has(&self, slug: &str, role: OrgRole) -> bool {
268 self.membership(slug)
269 .is_some_and(|membership| membership.role == Role::Owner || membership.has(role))
270 }
271
272 /// Whether the user may manage `slug`'s billing: an owner or a billing
273 /// manager.
274 pub fn manages_billing(&self, slug: &str) -> bool {
275 self.owns_or_has(slug, OrgRole::BillingManager)
276 }
277
278 /// Whether the user may see and manage security across `slug`: an
279 /// owner or a security manager.
280 pub fn manages_security(&self, slug: &str) -> bool {
281 self.owns_or_has(slug, OrgRole::SecurityManager)
282 }
283
284 /// The workspace's member privileges as this user sees them: the
285 /// defaults when the membership does not say.
286 pub fn privileges_in(&self, slug: &str) -> MemberPrivileges {
287 self.membership(slug).and_then(|membership| membership.privileges).unwrap_or_default()
288 }
Icons are cached at the edge289}
290
291/// Who is asking. Every read and write in every service takes one.
292pub type Viewer = Option<User>;

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