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

Billing, integrations, security and identity no longer serve g1t's own agents. Billing stops metering agent runs, model tokens and AI Gateway requests, drops its model catalogue and price-keeper model prices, and stops selling AI credit, which only ever paid for those; credit bought earlier still pays toward what is owed. A usage report, statement or invoice that holds an old agent or model meter shows it as "Other usage" rather than failing, and the get_ai_credit and buy_ai_credit API operations and MCP billing actions go. Integrations no longer connects model providers or routes models, and no longer assigns imported issues or alerts to g1t; a model provider already connected can still be disconnected. Security drops "Fix with g1t". Identity no longer creates agent tokens or puts agents on teams, a team's lead is a person, and run credentials are issued only for checks, the merge queue, merge checks, deployments and bumps; tokens and credentials already issued keep working until they expire. The reserved names g1t and g1t-agent stay reserved. No tables are dropped.1//! Run credentials: a token per sandbox run (checks, the merge queue, a
2//! merge check, a deployment or a security update's bump), bound to the
3//! run, its repository and what its kind of work needs, acting as g1t on
4//! behalf of the person who started the work, or of the workspace for
5//! g1t's own. See `g1t_contracts::credentials` for the policy.
6//!
7//! Credentials made for agent runs before g1t stopped running agents keep
8//! resolving until they expire (at most six hours), so nothing in flight
9//! breaks; no new ones are made.
Fixes from the page sweep10
11use g1t_contracts::credentials::{
The contracts no longer describe g1t's own agents, and workspaces can keep their AI providers. Every consumer had already stopped using them, so the TypeScript and Rust contracts drop the workspace-agent, ability, look, skill-library, context, runner-agent and mention modules, the chat and docs RPCs agents posted and read through, the folio agent methods, the agent_waiting notification, agent.asked and memory.changed events, AI credit, token and gateway billing types, model routes and sessions, team agents, agent tokens, plan, review, message and confidence types, command rules, cost caps and confidence rules. The agents:run and models:* scopes are no longer offered by any preset, OAuth default or permission form, but a stored token or grant that names them still reads; and the removed operations are gone from the scope table, so the API's check that every operation has exactly one scope is strict again. What stored data needs in order to parse (old run and credential kinds, an agent team lead, retired rules and webhook events, old guardrail and integration settings) still parses, and a run's token is still PrincipalKind::Agent, which now means a run's token and the @g1t rows written before. The customize, marketplace, skills and claude-plugin contracts stay only until the mobile app drops its Customize screens.12 Acting, BindRunCredentialsArgs, CreateRunCredentialArgs, CredentialUse, Principal, RevokeRunCredentialsArgs,
Billing, integrations, security and identity no longer serve g1t's own agents. Billing stops metering agent runs, model tokens and AI Gateway requests, drops its model catalogue and price-keeper model prices, and stops selling AI credit, which only ever paid for those; credit bought earlier still pays toward what is owed. A usage report, statement or invoice that holds an old agent or model meter shows it as "Other usage" rather than failing, and the get_ai_credit and buy_ai_credit API operations and MCP billing actions go. Integrations no longer connects model providers or routes models, and no longer assigns imported issues or alerts to g1t; a model provider already connected can still be disconnected. Security drops "Fix with g1t". Identity no longer creates agent tokens or puts agents on teams, a team's lead is a person, and run credentials are issued only for checks, the merge queue, merge checks, deployments and bumps; tokens and credentials already issued keep working until they expire. The reserved names g1t and g1t-agent stay reserved. No tables are dropped.13 RunBinding, RunCredentialKind, intersect, intersect_grants, operations_for,
Fixes from the page sweep14};
15use g1t_contracts::identity::{
16 AGENT_ID, AGENT_NAME, AgentScope, CreateAccessTokenArgs, CreatedAccessToken,
17};
18use g1t_contracts::time::SQL_NOW;
19use g1t_contracts::{PrincipalKind, User, Viewer};
20use worker::Result;
21use worker::wasm_bindgen::JsValue;
22
23use crate::Identity;
24
25/// No run outlives this, whatever its caller asks for.
26const MAX_RUN_TTL_SECONDS: u64 = 6 * 60 * 60;
27const MIN_RUN_TTL_SECONDS: u64 = 60;
28/// More hashes than one sandbox ever holds.
29const MAX_HASHES: usize = 8;
30
The contracts no longer describe g1t's own agents, and workspaces can keep their AI providers. Every consumer had already stopped using them, so the TypeScript and Rust contracts drop the workspace-agent, ability, look, skill-library, context, runner-agent and mention modules, the chat and docs RPCs agents posted and read through, the folio agent methods, the agent_waiting notification, agent.asked and memory.changed events, AI credit, token and gateway billing types, model routes and sessions, team agents, agent tokens, plan, review, message and confidence types, command rules, cost caps and confidence rules. The agents:run and models:* scopes are no longer offered by any preset, OAuth default or permission form, but a stored token or grant that names them still reads; and the removed operations are gone from the scope table, so the API's check that every operation has exactly one scope is strict again. What stored data needs in order to parse (old run and credential kinds, an agent team lead, retired rules and webhook events, old guardrail and integration settings) still parses, and a run's token is still PrincipalKind::Agent, which now means a run's token and the @g1t rows written before. The customize, marketplace, skills and claude-plugin contracts stay only until the mobile app drops its Customize screens.31/// Whether a credential is still made for this kind of run and use: a
32/// runner's, for sandbox work that is not one of the retired hosted
33/// agents' (`RunCredentialKind::retired`).
34fn issued_for(kind: RunCredentialKind, usage: CredentialUse) -> bool {
35 !kind.retired() && usage == CredentialUse::Runner
Billing, integrations, security and identity no longer serve g1t's own agents. Billing stops metering agent runs, model tokens and AI Gateway requests, drops its model catalogue and price-keeper model prices, and stops selling AI credit, which only ever paid for those; credit bought earlier still pays toward what is owed. A usage report, statement or invoice that holds an old agent or model meter shows it as "Other usage" rather than failing, and the get_ai_credit and buy_ai_credit API operations and MCP billing actions go. Integrations no longer connects model providers or routes models, and no longer assigns imported issues or alerts to g1t; a model provider already connected can still be disconnected. Security drops "Fix with g1t". Identity no longer creates agent tokens or puts agents on teams, a team's lead is a person, and run credentials are issued only for checks, the merge queue, merge checks, deployments and bumps; tokens and credentials already issued keep working until they expire. The reserved names g1t and g1t-agent stay reserved. No tables are dropped.36}
37
Fixes from the page sweep38/// A SHA-256 in lowercase hex, as tokens are stored.
39fn is_hash(value: &str) -> bool {
40 value.len() == 64
41 && value
42 .bytes()
43 .all(|b| b.is_ascii_digit() || (b'a'..=b'f').contains(&b))
44}
45
46impl Identity {
47 /// The composite identity behind an agent's token: the agent, acting
48 /// for the person (or workspace) the token was made for, in the run's
49 /// workspace only, and only while that person still belongs to it.
50 pub(crate) async fn agent_principal(
51 &self,
52 credential_id: &str,
53 user_id: Option<&str>,
54 workspace_id: Option<&str>,
55 scope: AgentScope,
56 ) -> Result<Viewer> {
57 let person = match (user_id, workspace_id) {
58 (Some(id), _) => {
59 self.find_user(
60 "SELECT id, username, email_verified_at IS NOT NULL AS verified
Merge account deletion: soft delete for 30 days, staff restore and purge, ghost for what remains (identity 0037)61 FROM users WHERE id = ? AND deleted_at IS NULL",
Fixes from the page sweep62 id,
63 )
64 .await?
65 }
66 (None, Some(id)) => self.workspace_principal(id).await?,
67 (None, None) => None,
68 };
69 // The person is gone: so is everything that acted for them.
70 let Some(person) = person else {
71 return Ok(None);
72 };
73 let agent = scope
74 .run
75 .as_ref()
76 .map(|run| run.agent.clone())
77 .unwrap_or_else(|| AGENT_NAME.to_owned());
78 // g1t's own run: the workspace's credential, acting as g1t, so the
79 // pull request and working copy g1t opened are its own (run.system).
80 let on_behalf_of = if scope.run.as_ref().is_some_and(|run| run.system) {
81 Principal {
82 id: g1t_contracts::system::ID.to_owned(),
83 username: g1t_contracts::system::USERNAME.to_owned(),
84 }
85 } else {
86 Principal {
87 id: person.id,
88 username: person.username,
89 }
90 };
91 Ok(Some(User {
92 id: AGENT_ID.to_owned(),
93 username: AGENT_NAME.to_owned(),
94 kind: PrincipalKind::Agent,
95 verified: person.verified,
96 workspaces: intersect(&person.workspaces, &scope.repo.namespace),
97 // The person's roles on the workspace's repositories, so an
98 // outside collaborator's agent works where they may, and never
99 // beyond Write (credentials::AGENT_CEILING).
100 grants: intersect_grants(&person.grants, &scope.repo.namespace),
101 acting: Some(Box::new(Acting {
102 credential_id: credential_id.to_owned(),
103 agent,
104 on_behalf_of,
105 scope,
106 })),
107 ..User::default()
108 }))
109 }
110
111 pub async fn create_run_credential(
112 &self,
113 a: CreateRunCredentialArgs,
114 ) -> Result<CreatedAccessToken> {
The contracts no longer describe g1t's own agents, and workspaces can keep their AI providers. Every consumer had already stopped using them, so the TypeScript and Rust contracts drop the workspace-agent, ability, look, skill-library, context, runner-agent and mention modules, the chat and docs RPCs agents posted and read through, the folio agent methods, the agent_waiting notification, agent.asked and memory.changed events, AI credit, token and gateway billing types, model routes and sessions, team agents, agent tokens, plan, review, message and confidence types, command rules, cost caps and confidence rules. The agents:run and models:* scopes are no longer offered by any preset, OAuth default or permission form, but a stored token or grant that names them still reads; and the removed operations are gone from the scope table, so the API's check that every operation has exactly one scope is strict again. What stored data needs in order to parse (old run and credential kinds, an agent team lead, retired rules and webhook events, old guardrail and integration settings) still parses, and a run's token is still PrincipalKind::Agent, which now means a run's token and the @g1t rows written before. The customize, marketplace, skills and claude-plugin contracts stay only until the mobile app drops its Customize screens.115 if !issued_for(a.kind, a.usage) {
Billing, integrations, security and identity no longer serve g1t's own agents. Billing stops metering agent runs, model tokens and AI Gateway requests, drops its model catalogue and price-keeper model prices, and stops selling AI credit, which only ever paid for those; credit bought earlier still pays toward what is owed. A usage report, statement or invoice that holds an old agent or model meter shows it as "Other usage" rather than failing, and the get_ai_credit and buy_ai_credit API operations and MCP billing actions go. Integrations no longer connects model providers or routes models, and no longer assigns imported issues or alerts to g1t; a model provider already connected can still be disconnected. Security drops "Fix with g1t". Identity no longer creates agent tokens or puts agents on teams, a team's lead is a person, and run credentials are issued only for checks, the merge queue, merge checks, deployments and bumps; tokens and credentials already issued keep working until they expire. The reserved names g1t and g1t-agent stay reserved. No tables are dropped.116 return Err(worker::Error::RustError(format!(
The contracts no longer describe g1t's own agents, and workspaces can keep their AI providers. Every consumer had already stopped using them, so the TypeScript and Rust contracts drop the workspace-agent, ability, look, skill-library, context, runner-agent and mention modules, the chat and docs RPCs agents posted and read through, the folio agent methods, the agent_waiting notification, agent.asked and memory.changed events, AI credit, token and gateway billing types, model routes and sessions, team agents, agent tokens, plan, review, message and confidence types, command rules, cost caps and confidence rules. The agents:run and models:* scopes are no longer offered by any preset, OAuth default or permission form, but a stored token or grant that names them still reads; and the removed operations are gone from the scope table, so the API's check that every operation has exactly one scope is strict again. What stored data needs in order to parse (old run and credential kinds, an agent team lead, retired rules and webhook events, old guardrail and integration settings) still parses, and a run's token is still PrincipalKind::Agent, which now means a run's token and the @g1t rows written before. The customize, marketplace, skills and claude-plugin contracts stay only until the mobile app drops its Customize screens.117 "no run credential is made for {} runs' {}",
118 a.kind.as_str(),
119 a.usage.as_str()
Billing, integrations, security and identity no longer serve g1t's own agents. Billing stops metering agent runs, model tokens and AI Gateway requests, drops its model catalogue and price-keeper model prices, and stops selling AI credit, which only ever paid for those; credit bought earlier still pays toward what is owed. A usage report, statement or invoice that holds an old agent or model meter shows it as "Other usage" rather than failing, and the get_ai_credit and buy_ai_credit API operations and MCP billing actions go. Integrations no longer connects model providers or routes models, and no longer assigns imported issues or alerts to g1t; a model provider already connected can still be disconnected. Security drops "Fix with g1t". Identity no longer creates agent tokens or puts agents on teams, a team's lead is a person, and run credentials are issued only for checks, the merge queue, merge checks, deployments and bumps; tokens and credentials already issued keep working until they expire. The reserved names g1t and g1t-agent stay reserved. No tables are dropped.120 )));
121 }
122 let agent = AGENT_NAME.to_owned();
Fixes from the page sweep123 let scope = AgentScope {
124 repo: a.repo.clone(),
125 operations: operations_for(a.kind, a.usage)
126 .into_iter()
127 .map(str::to_owned)
128 .collect(),
129 run: Some(RunBinding {
130 kind: a.kind,
131 usage: a.usage,
132 run_id: None,
133 number: a.number,
134 agent: agent.clone(),
135 system: a.on_behalf_of.kind == PrincipalKind::System,
136 read: a.read,
137 push: a.push,
138 }),
139 };
Billing, integrations, security and identity no longer serve g1t's own agents. Billing stops metering agent runs, model tokens and AI Gateway requests, drops its model catalogue and price-keeper model prices, and stops selling AI credit, which only ever paid for those; credit bought earlier still pays toward what is owed. A usage report, statement or invoice that holds an old agent or model meter shows it as "Other usage" rather than failing, and the get_ai_credit and buy_ai_credit API operations and MCP billing actions go. Integrations no longer connects model providers or routes models, and no longer assigns imported issues or alerts to g1t; a model provider already connected can still be disconnected. Security drops "Fix with g1t". Identity no longer creates agent tokens or puts agents on teams, a team's lead is a person, and run credentials are issued only for checks, the merge queue, merge checks, deployments and bumps; tokens and credentials already issued keep working until they expire. The reserved names g1t and g1t-agent stay reserved. No tables are dropped.140 // g1t's own work (a security update's bump) has no person behind it: its credential acts for the workspace,
Fixes from the page sweep141 // as a workspace's own token would.
142 let on_behalf_of = if a.on_behalf_of.kind == PrincipalKind::System {
143 match self.workspace_id_of(&a.repo.namespace).await? {
144 Some(id) => User {
145 id,
146 username: a.repo.namespace.to_lowercase(),
147 kind: PrincipalKind::Workspace,
148 ..User::default()
149 },
150 None => return Err(worker::Error::RustError(format!("no workspace {}", a.repo.namespace))),
151 }
152 } else {
153 a.on_behalf_of
154 };
155 let created = self
156 .create_access_token(CreateAccessTokenArgs {
157 user: on_behalf_of,
158 name: format!(
159 "{agent}: {} run in {}/{}{}",
160 a.kind.as_str(),
161 a.repo.namespace,
162 a.repo.name,
163 a.number.map(|n| format!("#{n}")).unwrap_or_default()
164 ),
165 ttl_seconds: Some(
166 a.ttl_seconds
167 .clamp(MIN_RUN_TTL_SECONDS, MAX_RUN_TTL_SECONDS),
168 ),
169 // A run credential's scope is its run's; see agent_scope.
170 scopes: None,
171 listed: false,
172 })
173 .await?;
174 self.db
175 .prepare("UPDATE access_tokens SET agent_scope = ? WHERE id = ?")
176 .bind(&[
177 serde_json::to_string(&scope)?.into(),
178 created.info.id.as_str().into(),
179 ])?
180 .run()
181 .await?;
182 Ok(created)
183 }
184
Billing, integrations, security and identity no longer serve g1t's own agents. Billing stops metering agent runs, model tokens and AI Gateway requests, drops its model catalogue and price-keeper model prices, and stops selling AI credit, which only ever paid for those; credit bought earlier still pays toward what is owed. A usage report, statement or invoice that holds an old agent or model meter shows it as "Other usage" rather than failing, and the get_ai_credit and buy_ai_credit API operations and MCP billing actions go. Integrations no longer connects model providers or routes models, and no longer assigns imported issues or alerts to g1t; a model provider already connected can still be disconnected. Security drops "Fix with g1t". Identity no longer creates agent tokens or puts agents on teams, a team's lead is a person, and run credentials are issued only for checks, the merge queue, merge checks, deployments and bumps; tokens and credentials already issued keep working until they expire. The reserved names g1t and g1t-agent stay reserved. No tables are dropped.185 /// Ties a sandbox's credentials to the run it recorded. A token
Fixes from the page sweep186 /// already bound keeps its run.
187 pub async fn bind_run_credentials(&self, a: BindRunCredentialsArgs) -> Result<bool> {
188 let hashes: Vec<&String> = a
189 .token_hashes
190 .iter()
191 .filter(|hash| is_hash(hash))
192 .take(MAX_HASHES)
193 .collect();
194 if hashes.is_empty() || a.run_id.trim().is_empty() {
195 return Ok(false);
196 }
197 let marks = vec!["?"; hashes.len()].join(", ");
198 let mut values: Vec<JsValue> = vec![a.run_id.as_str().into(), a.run_id.as_str().into()];
199 values.extend(hashes.iter().map(|hash| JsValue::from(hash.as_str())));
200 self.db
201 .prepare(format!(
202 "UPDATE access_tokens
203 SET run_id = ?, agent_scope = json_set(agent_scope, '$.run.runId', ?)
204 WHERE token_hash IN ({marks}) AND run_id IS NULL
205 AND json_extract(agent_scope, '$.run') IS NOT NULL"
206 ))
207 .bind(&values)?
208 .run()
209 .await?;
210 Ok(true)
211 }
212
213 /// Ends a sandbox's credentials: they stop working at once. Only run
214 /// credentials are touched.
215 pub async fn revoke_run_credentials(&self, a: RevokeRunCredentialsArgs) -> Result<bool> {
216 let hashes: Vec<&String> = a
217 .token_hashes
218 .iter()
219 .filter(|hash| is_hash(hash))
220 .take(MAX_HASHES)
221 .collect();
222 let mut conditions = Vec::new();
223 let mut values: Vec<JsValue> = Vec::new();
224 if !hashes.is_empty() {
225 conditions.push(format!(
226 "token_hash IN ({})",
227 vec!["?"; hashes.len()].join(", ")
228 ));
229 values.extend(hashes.iter().map(|hash| JsValue::from(hash.as_str())));
230 }
231 if let Some(run_id) = a.run_id.as_deref().filter(|id| !id.trim().is_empty()) {
232 conditions.push("run_id = ?".to_owned());
233 values.push(run_id.into());
234 }
235 if conditions.is_empty() {
236 return Ok(false);
237 }
238 self.db
239 .prepare(format!(
240 "UPDATE access_tokens SET expires_at = {SQL_NOW}
241 WHERE ({}) AND json_extract(agent_scope, '$.run') IS NOT NULL
242 AND (expires_at IS NULL OR expires_at > {SQL_NOW})",
243 conditions.join(" OR ")
244 ))
245 .bind(&values)?
246 .run()
247 .await?;
248 Ok(true)
249 }
250}
251
252#[cfg(test)]
253mod tests {
The contracts no longer describe g1t's own agents, and workspaces can keep their AI providers. Every consumer had already stopped using them, so the TypeScript and Rust contracts drop the workspace-agent, ability, look, skill-library, context, runner-agent and mention modules, the chat and docs RPCs agents posted and read through, the folio agent methods, the agent_waiting notification, agent.asked and memory.changed events, AI credit, token and gateway billing types, model routes and sessions, team agents, agent tokens, plan, review, message and confidence types, command rules, cost caps and confidence rules. The agents:run and models:* scopes are no longer offered by any preset, OAuth default or permission form, but a stored token or grant that names them still reads; and the removed operations are gone from the scope table, so the API's check that every operation has exactly one scope is strict again. What stored data needs in order to parse (old run and credential kinds, an agent team lead, retired rules and webhook events, old guardrail and integration settings) still parses, and a run's token is still PrincipalKind::Agent, which now means a run's token and the @g1t rows written before. The customize, marketplace, skills and claude-plugin contracts stay only until the mobile app drops its Customize screens.254 use super::{CredentialUse, RunCredentialKind, is_hash, issued_for};
Billing, integrations, security and identity no longer serve g1t's own agents. Billing stops metering agent runs, model tokens and AI Gateway requests, drops its model catalogue and price-keeper model prices, and stops selling AI credit, which only ever paid for those; credit bought earlier still pays toward what is owed. A usage report, statement or invoice that holds an old agent or model meter shows it as "Other usage" rather than failing, and the get_ai_credit and buy_ai_credit API operations and MCP billing actions go. Integrations no longer connects model providers or routes models, and no longer assigns imported issues or alerts to g1t; a model provider already connected can still be disconnected. Security drops "Fix with g1t". Identity no longer creates agent tokens or puts agents on teams, a team's lead is a person, and run credentials are issued only for checks, the merge queue, merge checks, deployments and bumps; tokens and credentials already issued keep working until they expire. The reserved names g1t and g1t-agent stay reserved. No tables are dropped.255
256 #[test]
257 fn credentials_are_made_only_for_sandbox_work_that_is_not_an_agents() {
The contracts no longer describe g1t's own agents, and workspaces can keep their AI providers. Every consumer had already stopped using them, so the TypeScript and Rust contracts drop the workspace-agent, ability, look, skill-library, context, runner-agent and mention modules, the chat and docs RPCs agents posted and read through, the folio agent methods, the agent_waiting notification, agent.asked and memory.changed events, AI credit, token and gateway billing types, model routes and sessions, team agents, agent tokens, plan, review, message and confidence types, command rules, cost caps and confidence rules. The agents:run and models:* scopes are no longer offered by any preset, OAuth default or permission form, but a stored token or grant that names them still reads; and the removed operations are gone from the scope table, so the API's check that every operation has exactly one scope is strict again. What stored data needs in order to parse (old run and credential kinds, an agent team lead, retired rules and webhook events, old guardrail and integration settings) still parses, and a run's token is still PrincipalKind::Agent, which now means a run's token and the @g1t rows written before. The customize, marketplace, skills and claude-plugin contracts stay only until the mobile app drops its Customize screens.258 let issued: Vec<&str> = RunCredentialKind::ALL
259 .iter()
260 .filter(|kind| issued_for(**kind, CredentialUse::Runner))
261 .map(|kind| kind.as_str())
262 .collect();
Billing, integrations, security and identity no longer serve g1t's own agents. Billing stops metering agent runs, model tokens and AI Gateway requests, drops its model catalogue and price-keeper model prices, and stops selling AI credit, which only ever paid for those; credit bought earlier still pays toward what is owed. A usage report, statement or invoice that holds an old agent or model meter shows it as "Other usage" rather than failing, and the get_ai_credit and buy_ai_credit API operations and MCP billing actions go. Integrations no longer connects model providers or routes models, and no longer assigns imported issues or alerts to g1t; a model provider already connected can still be disconnected. Security drops "Fix with g1t". Identity no longer creates agent tokens or puts agents on teams, a team's lead is a person, and run credentials are issued only for checks, the merge queue, merge checks, deployments and bumps; tokens and credentials already issued keep working until they expire. The reserved names g1t and g1t-agent stay reserved. No tables are dropped.263 assert_eq!(issued, ["checks", "queue", "mergecheck", "deploy", "bump"]);
The contracts no longer describe g1t's own agents, and workspaces can keep their AI providers. Every consumer had already stopped using them, so the TypeScript and Rust contracts drop the workspace-agent, ability, look, skill-library, context, runner-agent and mention modules, the chat and docs RPCs agents posted and read through, the folio agent methods, the agent_waiting notification, agent.asked and memory.changed events, AI credit, token and gateway billing types, model routes and sessions, team agents, agent tokens, plan, review, message and confidence types, command rules, cost caps and confidence rules. The agents:run and models:* scopes are no longer offered by any preset, OAuth default or permission form, but a stored token or grant that names them still reads; and the removed operations are gone from the scope table, so the API's check that every operation has exactly one scope is strict again. What stored data needs in order to parse (old run and credential kinds, an agent team lead, retired rules and webhook events, old guardrail and integration settings) still parses, and a run's token is still PrincipalKind::Agent, which now means a run's token and the @g1t rows written before. The customize, marketplace, skills and claude-plugin contracts stay only until the mobile app drops its Customize screens.264 // A retired hosted agent's tools token is never made.
265 assert!(RunCredentialKind::ALL.iter().all(|kind| !issued_for(*kind, CredentialUse::Tools)));
Billing, integrations, security and identity no longer serve g1t's own agents. Billing stops metering agent runs, model tokens and AI Gateway requests, drops its model catalogue and price-keeper model prices, and stops selling AI credit, which only ever paid for those; credit bought earlier still pays toward what is owed. A usage report, statement or invoice that holds an old agent or model meter shows it as "Other usage" rather than failing, and the get_ai_credit and buy_ai_credit API operations and MCP billing actions go. Integrations no longer connects model providers or routes models, and no longer assigns imported issues or alerts to g1t; a model provider already connected can still be disconnected. Security drops "Fix with g1t". Identity no longer creates agent tokens or puts agents on teams, a team's lead is a person, and run credentials are issued only for checks, the merge queue, merge checks, deployments and bumps; tokens and credentials already issued keep working until they expire. The reserved names g1t and g1t-agent stay reserved. No tables are dropped.266 }
Fixes from the page sweep267
268 #[test]
269 fn only_hashes_are_taken() {
270 assert!(is_hash(&"a1".repeat(32)));
271 assert!(!is_hash(&"A1".repeat(32)));
272 assert!(!is_hash("g1t_0123"));
273 assert!(!is_hash(&"0".repeat(63)));
274 }
275}

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