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

Mission control shows where you are needed and what agents landed without you; git answers in about 200ms1//! 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;
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms8pub mod access;
Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r99pub mod advisories;
Merge account deletion: soft delete for 30 days, staff restore and purge, ghost for what remains (identity 0037)10pub mod account_deletion;
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms11pub mod accounts;
12pub mod actions;
13pub mod agents;
14pub mod audit;
Merge branch 'worktree-agent-ac5b181a013e54348'15pub mod backups;
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms16pub mod billing;
17pub 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;
Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r920pub mod coding_agents;
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms21pub 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 yet22pub mod datasets;
Merge branch 'worktree-agent-a5a5de74d8863d554' into worktree-agent-a16631325aecf58ca23pub mod deploy_keys;
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms24pub 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 yet25pub mod folios;
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms26pub mod github;
27pub mod guardrails;
28pub mod identity;
Inbox: the events service tells people what needs them as events arrive29pub mod inbox;
Merge branch 'worktree-agent-a5c94df323642630e'30pub mod live;
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms31pub mod integrations;
Merge main (membership, two-factor, GitHub repo roles) into tokens32pub mod members;
Merge branch 'mirroring' into artifacts-mode33pub mod mirrors;
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms34mod ids;
35mod names;
36mod outcome;
Packages, with a container registry on g1t.sh; workspaces deleted whole and kept 30 days; Members for every member37pub 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.38pub mod people;
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms39pub mod projects;
40pub mod repos;
Merge rulesets: branch and tag rules, agent-first, enforced on push and merge41pub mod rules;
Fast pages, required checks on the branch, self-hosted runners, honest incidents42pub mod runners;
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step43pub mod scopes;
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms44pub mod search;
45pub mod security;
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar46pub mod teams;
47pub mod security_suite;
Merge branch 'worktree-agent-ad8a36dfcd4176015' into spend-guardrails48pub mod subscribers;
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms49pub mod time;
Fine-grained personal tokens, workspace token rules and approvals in identity50pub mod tokens;
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar51pub mod updates;
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms52pub mod webhooks;
53pub mod work;
54
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.55pub use ids::{id_floor, new_id};
Merge branch 'worktree-agent-a8385d293d42c913a'56pub use names::{
A workflow's `uses: actions/setup-node@v4` means GitHub's `actions` again, whoever is on g1t. g1t looked for a repository on g1t before GitHub, and anyone could make a public workspace called `actions`, `docker` or `aws-actions` and have its `setup-node` run in every workflow that names GitHub's, with that job's secrets. Now another workspace's public repository answers only for a name GitHub has no public repository of; the caller's own workspace and g1t's own `g1t/…` still answer from g1t, and when GitHub can't be asked, GitHub's is used. The names of the GitHub accounts whose actions workflows use most can no longer be registered, renamed to, or taken by signing up with GitHub (which suggests the name with `-gh`); an account that has one keeps it, and mentions and invitations still find it. The Actions, authentication and workspaces guides say so.57 Username, aliasable_name, claimable_namespace, is_action_owner_name, is_claimable_name, claimable_username, is_namespace_shaped, is_reserved_name, is_route_name,
One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers58 is_valid_namespace, is_valid_repo_name,
Merge branch 'worktree-agent-a8385d293d42c913a'59};
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms60pub use outcome::{Failure, FailureCode, Outcome};
61
62use serde::{Deserialize, Serialize};
63
Merge main (membership, two-factor, GitHub repo roles) into tokens64/// What a member may do in a workspace. A member may also hold
65/// [`members::OrgRole`]s, which add to it.
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms66#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
67#[serde(rename_all = "lowercase")]
68pub enum Role {
Merge main (membership, two-factor, GitHub repo roles) into tokens69 /// Everything: Admin on every repository, the workspace's members,
70 /// settings, billing and security.
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms71 Owner,
Merge main (membership, two-factor, GitHub repo roles) into tokens72 /// The workspace's base permission on each repository, and what its
73 /// member privileges allow (see [`members::MemberPrivileges`]).
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms74 Member,
75}
76
Merge main (membership, two-factor, GitHub repo roles) into tokens77pub use members::{MemberPrivileges, OrgRole};
78
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms79/// One workspace a user belongs to.
80#[derive(Clone, Debug, Serialize, Deserialize)]
81pub struct Membership {
82 /// The workspace's name in URLs: `g1t.sh/<slug>`.
83 pub slug: String,
84 pub role: Role,
85 /// The workspace's display name, for showing it to people. Set when a
86 /// user is resolved from credentials; absent on principals made up by
87 /// a service.
88 #[serde(default, skip_serializing_if = "Option::is_none")]
89 pub name: Option<String>,
90 /// The workspace's uploaded icon: the SHA-256 of its bytes, served at
91 /// `/avatars/<avatar>`. Absent means the generated letter avatar.
92 #[serde(default, skip_serializing_if = "Option::is_none")]
93 pub avatar: Option<String>,
94 /// What a member gets on each of the workspace's repositories: the
95 /// workspace's base permission. Set when a user is resolved from
96 /// credentials; absent means the default, Write. Owners have Admin
97 /// whatever it says. See [`access`].
98 #[serde(default, skip_serializing_if = "Option::is_none")]
99 pub base_permission: Option<access::BasePermission>,
Merge branch 'worktree-agent-ad7c6d88d93adc817'100 /// Who may create the workspace's teams. Set when a user is resolved
101 /// from credentials; absent means the default, any member. See
102 /// [`teams::TeamCreation`].
103 #[serde(default, skip_serializing_if = "Option::is_none")]
104 pub team_creation: Option<teams::TeamCreation>,
Merge main (membership, two-factor, GitHub repo roles) into tokens105 /// The roles the member holds besides `role`: billing manager,
106 /// security manager. Set when a user is resolved from credentials.
107 #[serde(default, skip_serializing_if = "Vec::is_empty")]
108 pub org_roles: Vec<OrgRole>,
109 /// What the workspace lets members (and repository admins) do. Set
110 /// when a user is resolved from credentials; absent means the
111 /// defaults. See [`members::MemberPrivileges`].
112 #[serde(default, skip_serializing_if = "Option::is_none")]
113 pub privileges: Option<MemberPrivileges>,
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms114}
115
116impl Membership {
117 /// A plain member of `slug`, as services act inside one workspace.
118 pub fn member(slug: impl Into<String>) -> Self {
119 Membership {
120 slug: slug.into(),
121 role: Role::Member,
122 name: None,
123 avatar: None,
124 base_permission: None,
Merge branch 'worktree-agent-ad7c6d88d93adc817'125 team_creation: None,
Merge main (membership, two-factor, GitHub repo roles) into tokens126 org_roles: Vec::new(),
127 privileges: None,
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms128 }
129 }
Merge main (membership, two-factor, GitHub repo roles) into tokens130
131 /// Whether the member holds `role` besides owner or member.
132 pub fn has(&self, role: OrgRole) -> bool {
133 self.org_roles.contains(&role)
134 }
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms135}
136
137/// What a set of credentials resolved to.
138#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
139#[serde(rename_all = "lowercase")]
140pub enum PrincipalKind {
141 /// A person's account.
142 #[default]
143 User,
144 /// A workspace, acting through one of its own access tokens. Its `id`
145 /// is the workspace's, its `username` the workspace's slug, and it is a
146 /// member of that workspace and no other.
147 Workspace,
148 /// A g1t agent at work in a sandbox, acting through a token that lives
149 /// 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-agent150 /// one repository. Its `username` is `g1t`.
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms151 Agent,
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily152 /// g1t itself: the platform acting on its own, as when it opens a
153 /// pull request to upgrade a vulnerable dependency or merges from the
154 /// queue. Never resolved from credentials: only services make one,
155 /// with [`User::system`]. Its `username` is `g1t`, which nobody can
156 /// register.
157 System,
158}
159
160/// g1t's own identity, as [`PrincipalKind::System`] work is recorded.
161pub mod system {
162 /// Its id wherever an author or actor id is stored.
163 pub const ID: &str = "g1t";
164 /// Its name, shown as the author of what it does.
165 pub const USERNAME: &str = "g1t";
166 /// The address on the commits it makes, which no mailbox receives.
167 pub const EMAIL: &str = "g1t@users.noreply.g1t.sh";
168 /// Ids that earlier versions stored for g1t's own actions, such as a
169 /// merge its settings made. Read as g1t too.
170 pub const LEGACY_IDS: [&str; 3] = ["g1t_policy", "svc_runner", "g1t_runner"];
171
172 /// Whether `id` is g1t's own.
173 pub fn is_system_id(id: &str) -> bool {
174 id == ID || LEGACY_IDS.contains(&id)
175 }
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms176}
177
178#[derive(Clone, Debug, Default, Serialize, Deserialize)]
179pub struct User {
180 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 managers181 /// Lowercased: what the person is found, linked and mentioned by.
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms182 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 managers183 /// The username as its owner wrote it (`Ana`), when that differs from
184 /// `username`: what pages show. Set on the signed-in person and on
185 /// people looked up by name; absent elsewhere, where `username` is shown.
186 #[serde(default, skip_serializing_if = "Option::is_none")]
187 pub display_username: Option<String>,
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms188 #[serde(default)]
189 pub kind: PrincipalKind,
190 /// Whether the account's email address has been confirmed. Unverified
191 /// accounts can sign in but cannot create or change anything.
192 #[serde(default)]
193 pub verified: bool,
194 /// The workspaces this user belongs to. Filled in when a user is
195 /// resolved from credentials, so any service can authorize from it.
196 #[serde(default)]
197 pub workspaces: Vec<Membership>,
198 /// The person's uploaded avatar: the SHA-256 of its bytes, served at
199 /// `/avatars/<avatar>`. Absent means the generated letter avatar.
200 #[serde(default, skip_serializing_if = "Option::is_none")]
201 pub avatar: Option<String>,
202 /// Set on an agent resolved from its token: who it acts for, with which
203 /// credential, and what it may do. See [`credentials`].
204 #[serde(default, skip_serializing_if = "Option::is_none")]
205 pub acting: Option<Box<credentials::Acting>>,
206 /// The repositories this user has been given a role on directly,
207 /// whether or not they belong to its workspace. Filled in with
208 /// `workspaces`; see [`access`].
209 #[serde(default, skip_serializing_if = "Vec::is_empty")]
210 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 step211 /// Set on a user resolved from an access token: its scopes and the
212 /// workspaces or repositories it is limited to. Absent on a signed-in
213 /// session and on an agent (whose `acting` scope applies instead).
214 /// See [`scopes`].
215 #[serde(default, skip_serializing_if = "Option::is_none")]
216 pub token: Option<Box<scopes::TokenAccess>>,
Merge main (membership, two-factor, GitHub repo roles) into tokens217 /// The workspaces this person belongs to but cannot use until they
218 /// meet its policy, such as turning on two-factor authentication.
219 /// They are left out of `workspaces` and `grants` meanwhile. Set when
220 /// a person is resolved from a session.
221 #[serde(default, skip_serializing_if = "Vec::is_empty")]
222 pub held: Vec<members::PolicyHold>,
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms223}
224
225impl User {
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily226 /// g1t itself, acting in `workspace`: what the platform's own work,
227 /// such as security updates, is done and recorded as.
228 pub fn system(workspace: &str) -> User {
229 User {
230 id: system::ID.to_owned(),
231 username: system::USERNAME.to_owned(),
232 kind: PrincipalKind::System,
233 verified: true,
234 workspaces: vec![Membership::member(workspace.to_lowercase())],
235 ..User::default()
236 }
237 }
238
239 /// Whether this is g1t itself.
240 pub fn is_system(&self) -> bool {
241 self.kind == PrincipalKind::System
242 }
243
Merge email confirmation gate: a code and a link, nothing until confirmed (identity 0036)244 /// Whether this is a person whose account has not confirmed its email
245 /// address. Such an account can only confirm it (or change it, or sign
246 /// out): the site, the API, MCP and git refuse it everything else
247 /// ([`accounts::confirm_email_first`]).
248 pub fn awaits_confirmation(&self) -> bool {
249 self.kind == PrincipalKind::User && !self.verified
250 }
251
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms252 pub fn role_in(&self, slug: &str) -> Option<Role> {
253 self.workspaces
254 .iter()
255 .find(|membership| membership.slug == slug)
256 .map(|membership| membership.role)
257 }
258
259 pub fn is_member(&self, slug: &str) -> bool {
260 self.role_in(slug).is_some()
261 }
Merge main (membership, two-factor, GitHub repo roles) into tokens262
263 /// The membership in `slug`, if any.
264 pub fn membership(&self, slug: &str) -> Option<&Membership> {
265 self.workspaces.iter().find(|membership| membership.slug.eq_ignore_ascii_case(slug))
266 }
267
268 /// Whether this is a person who owns `slug`, or holds `role` in it.
269 pub fn owns_or_has(&self, slug: &str, role: OrgRole) -> bool {
270 self.membership(slug)
271 .is_some_and(|membership| membership.role == Role::Owner || membership.has(role))
272 }
273
274 /// Whether the user may manage `slug`'s billing: an owner or a billing
275 /// manager.
276 pub fn manages_billing(&self, slug: &str) -> bool {
277 self.owns_or_has(slug, OrgRole::BillingManager)
278 }
279
280 /// Whether the user may see and manage security across `slug`: an
281 /// owner or a security manager.
282 pub fn manages_security(&self, slug: &str) -> bool {
283 self.owns_or_has(slug, OrgRole::SecurityManager)
284 }
285
286 /// The workspace's member privileges as this user sees them: the
287 /// defaults when the membership does not say.
288 pub fn privileges_in(&self, slug: &str) -> MemberPrivileges {
289 self.membership(slug).and_then(|membership| membership.privileges).unwrap_or_default()
290 }
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms291}
292
293/// Who is asking. Every read and write in every service takes one.
294pub type Viewer = Option<User>;

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