g1t/apps/status/src/components.ts
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.
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 1 | /** |
| 2 | * The parts of g1t the page lists, and how each is checked. Every address | |
| 3 | * comes from the Worker's vars, so an installation of its own names its own | |
| 4 | * hosts; a part whose address is empty is not part of that installation | |
| 5 | * and is left off the page. | |
| 6 | * | |
| 7 | * Checks go over the public internet, as people reach g1t, so they measure | |
| 8 | * what people see. Billing has no public address of its own, so it is the | |
| 9 | * one part checked through a service binding, when there is one. | |
| 10 | */ | |
| 11 | ||
| 12 | /** The Worker's vars that say where things are. */ | |
| 13 | export type Targets = { | |
| 14 | /** The site: `https://g1t.sh`. */ | |
| 15 | SITE_URL: string; | |
| 16 | /** The API: `https://api.g1t.sh`. */ | |
| 17 | API_URL: string; | |
| 18 | MCP_URL: string; | |
| 19 | DOCS_URL: string; | |
| 20 | /** Where deployed apps live: `https://g1t.page`. */ | |
| 21 | PAGES_URL: string; | |
| 22 | MODELS_URL: string; | |
| 23 | /** A public repository that always exists, `owner/name`, to fetch refs of. */ | |
| 24 | PROBE_REPO: string; | |
| 25 | /** The site as browsers reach it, when the checks reach it another way. */ | |
| 26 | PUBLIC_SITE_URL?: string; | |
| 27 | }; | |
| 28 | ||
| 29 | /** One request a check makes, and the answer that means the part works. */ | |
| 30 | export type Step = { | |
| 31 | url: string; | |
| 32 | headers?: Record<string, string>; | |
| 33 | /** The status that means it works; any 2xx when absent. */ | |
| 34 | expect?: number; | |
| 35 | }; | |
| 36 | ||
| 37 | export type Check = | |
| 38 | | { kind: "http"; steps: Step[] } | |
| 39 | /** Billing, through its binding: reading its price book. */ | |
| 40 | | { kind: "billing" } | |
| Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily | 41 | /** Git storage, through the repos service binding: how the store answered lately. */ |
| 42 | | { kind: "storage" } | |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 43 | /** No check yet: the page says so rather than showing green. */ |
| 44 | | { kind: "none" }; | |
| 45 | ||
| 46 | export type ComponentInfo = { | |
| 47 | key: string; | |
| 48 | name: string; | |
| 49 | address: string; | |
| 50 | checks: string; | |
| 51 | /** Whether g1t as a whole is down when this is. */ | |
| 52 | core: boolean; | |
| 53 | check: Check; | |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 54 | /** Slower than this, it counts as degraded; `SLOW_MS` when absent. */ |
| 55 | slowMs?: number; | |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 56 | }; |
| 57 | ||
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 58 | /** |
| 59 | * The page-speed budget the status page holds the site to: the slower of a | |
| 60 | * public project page and Explore, to the first byte of the answer, from a | |
| 61 | * Cloudflare data centre. docs/PERFORMANCE.md has the targets. | |
| 62 | */ | |
| 63 | export const SPEED_BUDGET_MS = 800; | |
| 64 | ||
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 65 | /** A token no one holds: the API asks identity about it and refuses it. */ |
| 66 | export const NO_TOKEN = `g1t_${"0".repeat(40)}`; | |
| 67 | ||
| 68 | function host(url: string): string { | |
| 69 | try { | |
| 70 | return new URL(url).host; | |
| 71 | } catch { | |
| 72 | return url; | |
| 73 | } | |
| 74 | } | |
| 75 | ||
| 76 | const trim = (url: string | undefined) => (url ?? "").trim().replace(/\/+$/, ""); | |
| 77 | ||
| Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily | 78 | /** Git storage counts as degraded when its calls took longer than this on average. */ |
| 79 | export const STORAGE_SLOW_MS = 1500; | |
| 80 | ||
| 81 | /** The parts, in the order the page lists them. `storage`: whether the repos service is bound. */ | |
| 82 | export function components(vars: Partial<Targets>, billing = true, storage = false): ComponentInfo[] { | |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 83 | const site = trim(vars.SITE_URL); |
| 84 | const api = trim(vars.API_URL); | |
| 85 | const mcp = trim(vars.MCP_URL); | |
| 86 | const docs = trim(vars.DOCS_URL); | |
| 87 | const pages = trim(vars.PAGES_URL); | |
| 88 | const models = trim(vars.MODELS_URL); | |
| 89 | const repo = (vars.PROBE_REPO ?? "").trim(); | |
| 90 | // What the page shows as the site's address: where people reach it. | |
| 91 | const shown = host(trim(vars.PUBLIC_SITE_URL) || site); | |
| 92 | const list: (ComponentInfo | null)[] = [ | |
| 93 | site | |
| 94 | ? { | |
| 95 | key: "site", | |
| 96 | name: "Website and sign-in", | |
| 97 | address: shown, | |
| 98 | checks: api | |
| 99 | ? "The sign-in page loading, and the account service answering an access token through the API." | |
| 100 | : "The sign-in page loading.", | |
| 101 | core: true, | |
| 102 | check: { | |
| 103 | kind: "http", | |
| 104 | steps: [ | |
| 105 | { url: `${site}/login` }, | |
| 106 | ...(api ? [{ url: `${api}/v1/user`, headers: { authorization: `Bearer ${NO_TOKEN}` }, expect: 401 }] : []), | |
| 107 | ], | |
| 108 | }, | |
| 109 | } | |
| 110 | : null, | |
| 111 | api | |
| 112 | ? { | |
| 113 | key: "api", | |
| 114 | name: "API", | |
| 115 | address: host(api), | |
| 116 | checks: "The API's front page.", | |
| 117 | core: true, | |
| 118 | check: { kind: "http", steps: [{ url: `${api}/` }] }, | |
| 119 | } | |
| 120 | : null, | |
| 121 | site && repo | |
| 122 | ? { | |
| 123 | key: "git", | |
| 124 | name: "Git and repositories", | |
| 125 | address: `${shown}/<owner>/<repo>.git`, | |
| 126 | checks: "Listing the branches of a public repository over HTTPS, the first step of every clone.", | |
| 127 | core: true, | |
| 128 | check: { kind: "http", steps: [{ url: `${site}/${repo}.git/info/refs?service=git-upload-pack` }] }, | |
| 129 | } | |
| 130 | : null, | |
| Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily | 131 | storage && site |
| 132 | ? { | |
| 133 | key: "storage", | |
| 134 | name: "Git storage", | |
| 135 | address: "Where every repository is kept", | |
| 136 | checks: `How g1t's git storage answered over the last five minutes, as g1t saw it: failures, rate limits, and how long calls took. Rate limited, or slower than ${STORAGE_SLOW_MS} ms on average, counts as degraded.`, | |
| 137 | core: false, | |
| 138 | check: { kind: "storage" }, | |
| 139 | slowMs: STORAGE_SLOW_MS, | |
| 140 | } | |
| 141 | : null, | |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 142 | site && repo |
| 143 | ? { | |
| 144 | key: "speed", | |
| 145 | name: "Page speed", | |
| 146 | address: `${shown}/${repo}`, | |
| 147 | checks: `A public project page and Explore each answering within ${SPEED_BUDGET_MS} ms. Slower counts as degraded.`, | |
| 148 | core: false, | |
| 149 | check: { kind: "http", steps: [{ url: `${site}/${repo}` }, { url: `${site}/explore` }] }, | |
| 150 | slowMs: SPEED_BUDGET_MS, | |
| 151 | } | |
| 152 | : null, | |
| status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas | 153 | mcp |
| 154 | ? { | |
| 155 | key: "mcp", | |
| 156 | name: "MCP server", | |
| 157 | address: host(mcp), | |
| 158 | checks: "The MCP server's description.", | |
| 159 | core: false, | |
| 160 | check: { kind: "http", steps: [{ url: `${mcp}/`, headers: { accept: "application/json" } }] }, | |
| 161 | } | |
| 162 | : null, | |
| 163 | docs | |
| 164 | ? { | |
| 165 | key: "docs", | |
| 166 | name: "Documentation", | |
| 167 | address: host(docs), | |
| 168 | checks: "The documentation's front page.", | |
| 169 | core: false, | |
| 170 | check: { kind: "http", steps: [{ url: `${docs}/` }] }, | |
| 171 | } | |
| 172 | : null, | |
| 173 | pages | |
| 174 | ? { | |
| 175 | key: "deployments", | |
| 176 | name: "Deployments", | |
| 177 | address: `*.${host(pages)}`, | |
| 178 | checks: `${host(pages)} answering. Each deployed app is not checked one by one.`, | |
| 179 | core: false, | |
| 180 | check: { kind: "http", steps: [{ url: `${pages}/` }] }, | |
| 181 | } | |
| 182 | : null, | |
| 183 | models | |
| 184 | ? { | |
| 185 | key: "agents", | |
| 186 | name: "Agents' model proxy", | |
| 187 | address: host(models), | |
| 188 | checks: "The proxy agents reach their model through. The model providers behind it are not checked.", | |
| 189 | core: false, | |
| 190 | check: { kind: "http", steps: [{ url: `${models}/` }] }, | |
| 191 | } | |
| 192 | : null, | |
| 193 | models | |
| 194 | ? { | |
| 195 | key: "sandboxes", | |
| 196 | name: "Sandboxes", | |
| 197 | address: "Agents, checks, workflows and builds", | |
| 198 | checks: "Starting a sandbox costs money and takes seconds, so it is not checked from here yet.", | |
| 199 | core: false, | |
| 200 | check: { kind: "none" }, | |
| 201 | } | |
| 202 | : null, | |
| 203 | billing && site | |
| 204 | ? { | |
| 205 | key: "billing", | |
| 206 | name: "Billing", | |
| 207 | address: `${shown}/<workspace>/-/billing`, | |
| 208 | checks: "The billing service reading its price book. Stripe itself is not checked.", | |
| 209 | core: false, | |
| 210 | check: { kind: "billing" }, | |
| 211 | } | |
| 212 | : null, | |
| 213 | ]; | |
| 214 | return list.filter((c): c is ComponentInfo => c != null); | |
| 215 | } |