Anyone can sign up for g1t: with an email address and a password, or with GitHub, and no invite. The switch that made registration invite-only is gone rather than flipped, so it cannot be turned back on by a setting: identity's REGISTRATION_MODE, INVITES_PER_USER, INVITE_STAFF_WORKSPACES and WAITLIST_NOTIFY_EMAIL vars, the same in the self-hosted compose file and configs, RegistrationMode in both contracts, and the registration call the site asked once a minute.
What existed only to gate sign-up goes with it. The sign-up page has no invite-code field and no Request access form; a link with a good invite code still goes to the invite's own page, and a code that is no good is dropped and the form shown. Settings → Invites and its menu entries, personal invites to g1t (create_invite, list_invites, revoke_invite, and GET/POST/DELETE /user/invites with their MCP actions), the five-invite allowance and staff grants, staff-minted invites, shared invite links, the waitlist, its confirmation email and staff summary, and the GitHub sign-up's invite step. Inviting someone into a workspace or onto a repository works as before and never costs an invite; repository invitations to a new address had still been charged to the inviter's allowance, which they no longer are. Sudo's Invites page keeps one list, every invite sent with an invitation, to search and revoke; an account made with a shared link still says Joined through its label. No data is deleted: the waitlist, invite_grants, shared_invites and shared_invite_uses tables, and invites.charged_to, charged_workspace_id and staff, stay as they are, unused or read only. Sign-ups with a password are now rate limited, since nothing else stood in the way of a script making accounts: 5 an hour per client address, 100 an hour together for requests that carry none, counted once the form is well formed and before anything is looked up or written. GitHub sign-up needs a GitHub account with a verified address and is not counted. Email confirmation before anything else, the honeypot and the invite-failure throttle stay. The deploy smoke test now checks the sign-up page and sends it an address identity refuses before counting. The docs say anyone can sign up (accounts and authentication, GitHub, workspaces, the quickstart, self-hosting, the API and MCP references, limitations), and the API reference is regenerated.
| 8 | 8 | # migrate pending D1 migrations, before any code, once check and plan pass | |
| 9 | 9 | # core, edge, front the units of each stage, in jobs that share a build; | |
| 10 | 10 | # a stage starts only when the one before it succeeded | |
| 11 | − | # smoke sign-in, sign-up and the waitlist still work on g1t.sh | |
| 11 | + | # smoke sign-in and sign-up still work on g1t.sh | |
| 12 | 12 | # | |
| 13 | 13 | # Each run that deploys is one production deployment of g1t.sh, made by the | |
| 14 | 14 | # jobs that name `environment: production` (one per run, however many jobs): | |
| ⋯ | |||
| 301 | 301 | steps: *deploy | |
| 302 | 302 | ||
| 303 | 303 | # Once everything has deployed: the ways in for someone new still work. | |
| 304 | − | # The pages a visitor lands on load, and the waitlist form reaches | |
| 305 | − | # identity, sent an address it refuses before keeping anything, so the | |
| 306 | − | # real waitlist is never touched. scripts/ops/smoke.mjs. | |
| 304 | + | # The pages a visitor lands on load, and the sign-up form reaches | |
| 305 | + | # identity, sent an address it refuses before keeping or counting | |
| 306 | + | # anything, so no account is made. scripts/ops/smoke.mjs. | |
| 307 | 307 | smoke: | |
| 308 | 308 | name: Smoke | |
| 309 | 309 | needs: [check, plan, core, edge, front] | |
| ⋯ | |||
| 312 | 312 | timeout-minutes: 5 | |
| 313 | 313 | steps: | |
| 314 | 314 | - uses: actions/checkout@v5 | |
| 315 | − | - name: Sign-in, sign-up and the waitlist work | |
| 315 | + | - name: Sign-in and sign-up work | |
| 316 | 316 | run: node scripts/ops/smoke.mjs | |
| 87 | 87 | ), | |
| 88 | 88 | ( | |
| 89 | 89 | "Invites", | |
| 90 | − | "While g1t is invite-only, every new account needs an invite. Your invites, inviting people into a workspace by username or email, and answering the invitations to workspaces sent to you.", | |
| 90 | + | "Inviting people into a workspace by username or email, and answering the invitations to workspaces sent to you.", | |
| 91 | 91 | &[ | |
| 92 | − | Op::ListInvites, | |
| 93 | − | Op::CreateInvite, | |
| 94 | − | Op::RevokeInvite, | |
| 95 | 92 | Op::ListWorkspaceInvites, | |
| 96 | 93 | Op::InviteMember, | |
| 97 | 94 | Op::RevokeWorkspaceInvite, | |
| ⋯ | |||
| 678 | 675 | Op::ConfirmEmail => "Confirm an email address", | |
| 679 | 676 | Op::RemoveEmail => "Remove an email address", | |
| 680 | 677 | Op::UpdateEmailSettings => "Change your email settings", | |
| 681 | − | Op::ListInvites => "List your invites", | |
| 682 | − | Op::CreateInvite => "Create an invite", | |
| 683 | − | Op::RevokeInvite => "Revoke an invite", | |
| 684 | 678 | Op::ListWorkspaceInvites => "List a workspace's invites", | |
| 685 | 679 | Op::InviteMember => "Invite someone to a workspace", | |
| 686 | 680 | Op::ListInvitations => "List your workspace invitations", | |
| 133 | 133 | ConfirmEmail, | |
| 134 | 134 | RemoveEmail, | |
| 135 | 135 | UpdateEmailSettings, | |
| 136 | − | ListInvites, | |
| 137 | − | CreateInvite, | |
| 138 | − | RevokeInvite, | |
| 139 | 136 | ListWorkspaceInvites, | |
| 140 | 137 | InviteMember, | |
| 141 | 138 | RevokeWorkspaceInvite, | |
| ⋯ | |||
| 724 | 721 | } | |
| 725 | 722 | ||
| 726 | 723 | impl Op { | |
| 727 | − | pub const ALL: [Op; 408] = [ | |
| 724 | + | pub const ALL: [Op; 405] = [ | |
| 728 | 725 | Op::Whoami, | |
| 729 | 726 | Op::GetWorkspace, | |
| 730 | 727 | Op::CreateWorkspace, | |
| ⋯ | |||
| 740 | 737 | Op::ConfirmEmail, | |
| 741 | 738 | Op::RemoveEmail, | |
| 742 | 739 | Op::UpdateEmailSettings, | |
| 743 | − | Op::ListInvites, | |
| 744 | − | Op::CreateInvite, | |
| 745 | − | Op::RevokeInvite, | |
| 746 | 740 | Op::ListWorkspaceInvites, | |
| 747 | 741 | Op::InviteMember, | |
| 748 | 742 | Op::RevokeWorkspaceInvite, | |
| ⋯ | |||
| 1157 | 1151 | Op::ConfirmEmail => "confirm_email", | |
| 1158 | 1152 | Op::RemoveEmail => "remove_email", | |
| 1159 | 1153 | Op::UpdateEmailSettings => "update_email_settings", | |
| 1160 | − | Op::ListInvites => "list_invites", | |
| 1161 | − | Op::CreateInvite => "create_invite", | |
| 1162 | − | Op::RevokeInvite => "revoke_invite", | |
| 1163 | 1154 | Op::ListWorkspaceInvites => "list_workspace_invites", | |
| 1164 | 1155 | Op::InviteMember => "invite_member", | |
| 1165 | 1156 | Op::RevokeWorkspaceInvite => "revoke_workspace_invite", | |
| ⋯ | |||
| 1381 | 1372 | } | |
| 1382 | 1373 | Op::UpdateEmailSettings => { | |
| 1383 | 1374 | "Change what your addresses do; only the fields given change. `primary` is a confirmed address to make primary: account mail and password resets go there. `backup` is a confirmed address that also gets security notices, or an empty string for the primary only. Changing either needs your account `password`, and every confirmed address is told. `private_email` keeps your address off commits g1t makes for you (merges and changes made on the web, and agents' commits for you), which use your noreply address instead; `block_private_pushes` refuses pushes whose commits carry one of your addresses while it is private. People only." | |
| 1384 | − | } | |
| 1385 | − | Op::ListInvites => { | |
| 1386 | − | "Your invites, newest first, and how many you have left. While g1t is invite-only, every new account needs an invite code. You may have 5 invites out at once: pending and used ones count, and one revoked or expired before it was used comes back. `allowance.limit` is null when you have no limit. `workspaces` lists the workspaces you own that were granted invites to share. A pending invite's `code` is shown to you. `status` is `pending`; `awaiting_confirmation` (used to make an account that has not confirmed its address yet); `awaiting_answer` (used to make an account that has yet to accept or decline the workspace it was invited to); `redeemed`; `declined` (its person declined the workspace); `expired`; or `revoked`. An invite that brings someone into a workspace names it in `workspace`, with the `role` it joins with and, once known, the account it is for in `invitee`." | |
| 1387 | 1375 | } | |
| 1388 | − | Op::CreateInvite => { | |
| 1389 | − | "Make an invite. With `email`, it is sent there and only that address can use it; without, anyone with the code can, once. It works for 30 days. With `workspace`, the new account is brought into that workspace: once it confirms its address it gets an invitation to join as a member, which it accepts or declines, and no workspace of its own is made for it. That must be a workspace you own on the g1t plan; a free workspace is refused with `payment_required` (402). Without `workspace`, the new account gets a free workspace of its own. It uses one of your invites, or with `charge_workspace`, one of the invites g1t granted that workspace (its owners only). Returns the invite with its `code`; the link is https://g1t.sh/invite/<code>. People only: an agent's token or a workspace's token cannot make invites." | |
| 1390 | − | } | |
| 1391 | − | Op::RevokeInvite => { | |
| 1392 | − | "Revoke a pending invite you made, or one made for a workspace you own. It stops working at once, and the invite comes back to whoever it was charged to." | |
| 1393 | − | } | |
| 1394 | 1376 | Op::ListWorkspaceInvites => { | |
| 1395 | 1377 | "The invites made for a workspace, newest first, with each pending one's `code`. Owners only." | |
| 1396 | 1378 | } | |
| 1397 | 1379 | Op::InviteMember => { | |
| 1398 | − | "Invite someone into a workspace, by `username` or by `email`. Nobody joins without saying yes: they get an invitation to accept or decline, and join with `role` (`member` unless you give `owner`) when they accept. By `username`, the account gets the invitation in its inbox and by email, and it costs nothing. By `email`, it always makes an invite bound to that address and emails it the link, so the answer never says whether the address has a g1t account. Without one, the link makes the account, which is invited once it confirms its address; while g1t is invite-only that uses one of the workspace's granted invites, or else one of yours, and once anyone can sign up it costs nothing. With one, it costs nothing. Refused with `409` when the person is already a member or already has a pending invitation to the workspace. Owners only. A free workspace cannot invite anyone: this is refused with `payment_required` (402) until it starts the g1t plan, and an invite sent before cannot be accepted until then." | |
| 1380 | + | "Invite someone into a workspace, by `username` or by `email`. Nobody joins without saying yes: they get an invitation to accept or decline, and join with `role` (`member` unless you give `owner`) when they accept. By `username`, the account gets the invitation in its inbox and by email, and it costs nothing. By `email`, it always makes an invite bound to that address and emails it the link, so the answer never says whether the address has a g1t account. Without one, the link makes the account, which is invited once it confirms its address. Refused with `409` when the person is already a member or already has a pending invitation to the workspace. Owners only. A free workspace cannot invite anyone: this is refused with `payment_required` (402) until it starts the g1t plan, and an invite sent before cannot be accepted until then." | |
| 1399 | 1381 | } | |
| 1400 | 1382 | Op::RevokeWorkspaceInvite => "Revoke a workspace's pending invite. Owners only.", | |
| 1401 | 1383 | Op::ListInvitations => { | |
| ⋯ | |||
| 2007 | 1989 | }), | |
| 2008 | 1990 | &[], | |
| 2009 | 1991 | ), | |
| 2010 | − | Op::ListInvites => object(json!({}), &[]), | |
| 2011 | − | Op::CreateInvite => object( | |
| 2012 | − | json!({ | |
| 2013 | − | "email": { | |
| 2014 | − | "type": "string", | |
| 2015 | − | "description": "Only this address can use it, and it is emailed there. Left out, anyone with the code can.", | |
| 2016 | − | }, | |
| 2017 | − | "workspace": { | |
| 2018 | − | "type": "string", | |
| 2019 | − | "description": "The workspace the new account is invited to, by slug. Once it confirms its address it gets an invitation to join as a member, and no workspace of its own. One you own, on the g1t plan.", | |
| 2020 | − | }, | |
| 2021 | − | "charge_workspace": { | |
| 2022 | − | "type": "string", | |
| 2023 | − | "description": "Use one of the invites g1t granted this workspace instead of yours, by slug. Owners only.", | |
| 2024 | − | }, | |
| 2025 | − | }), | |
| 2026 | − | &[], | |
| 2027 | − | ), | |
| 2028 | − | Op::RevokeInvite => object( | |
| 2029 | − | json!({ "id": { "type": "string", "description": "The invite's id, such as inv_01k…" } }), | |
| 2030 | − | &["id"], | |
| 2031 | − | ), | |
| 2032 | 1992 | Op::ListWorkspaceInvites => object(json!({ "workspace": workspace_schema() }), &["workspace"]), | |
| 2033 | 1993 | Op::InviteMember => object( | |
| 2034 | 1994 | json!({ | |
| ⋯ | |||
| 3596 | 3556 | | Op::ConfirmEmail | |
| 3597 | 3557 | | Op::RemoveEmail | |
| 3598 | 3558 | | Op::UpdateEmailSettings | |
| 3599 | − | | Op::ListInvites | |
| 3600 | − | | Op::CreateInvite | |
| 3601 | − | | Op::RevokeInvite | |
| 3602 | 3559 | | Op::ListWorkspaceInvites | |
| 3603 | 3560 | | Op::InviteMember | |
| 3604 | 3561 | | Op::RevokeWorkspaceInvite | |
| ⋯ | |||
| 3910 | 3867 | "privateEmail": input["private_email"].as_bool(), | |
| 3911 | 3868 | "blockPrivatePushes": input["block_private_pushes"].as_bool(), | |
| 3912 | 3869 | "reauth": { "password": optional_text(input, "password") }, | |
| 3913 | − | }), | |
| 3914 | − | ) | |
| 3915 | − | .await | |
| 3916 | − | } | |
| 3917 | − | Op::ListInvites => { | |
| 3918 | − | let overview: g1t_contracts::identity::InvitesOverview = | |
| 3919 | − | g1t_kit::call(identity, "list_invites", &json!({ "user": actor() })).await?; | |
| 3920 | − | ok(&overview) | |
| 3921 | − | } | |
| 3922 | − | Op::CreateInvite => { | |
| 3923 | − | pass( | |
| 3924 | − | identity, | |
| 3925 | − | "create_invite", | |
| 3926 | − | &json!({ | |
| 3927 | − | "user": actor(), | |
| 3928 | − | "email": optional_text(input, "email"), | |
| 3929 | − | "workspace": optional_text(input, "charge_workspace"), | |
| 3930 | − | "join": optional_text(input, "workspace"), | |
| 3931 | − | "surface": services.audit.surface, | |
| 3932 | 3870 | }), | |
| 3933 | 3871 | ) | |
| 3934 | 3872 | .await | |
| 3935 | − | } | |
| 3936 | − | Op::RevokeInvite => { | |
| 3937 | − | pass(identity, "revoke_invite", &json!({ "user": actor(), "id": text(input, "id") })).await | |
| 3938 | 3873 | } | |
| 3939 | 3874 | Op::ListWorkspaceInvites => { | |
| 3940 | 3875 | pass(identity, "workspace_invites", &json!({ "slug": workspace(), "viewer": viewer })).await | |
| 383 | 383 | }, | |
| 384 | 384 | "notes": "Only the fields given change. `primary` and `backup` need `password`; `private_email` and `block_private_pushes` do not." | |
| 385 | 385 | }, | |
| 386 | − | "list_invites": { | |
| 387 | − | "response": { | |
| 388 | − | "mode": "invite", | |
| 389 | − | "allowance": { | |
| 390 | − | "limit": 5, | |
| 391 | − | "used": 2, | |
| 392 | − | "remaining": 3 | |
| 393 | − | }, | |
| 394 | − | "workspaces": [ | |
| 395 | − | { | |
| 396 | − | "slug": "acme-labs", | |
| 397 | − | "allowance": { | |
| 398 | − | "limit": 20, | |
| 399 | − | "used": 4, | |
| 400 | − | "remaining": 16 | |
| 401 | − | } | |
| 402 | − | } | |
| 403 | − | ], | |
| 404 | − | "invites": [ | |
| 405 | − | { | |
| 406 | − | "id": "inv_01kp2x7m8n9q0r1s2t3v4w5x6y", | |
| 407 | − | "code": "g1t-k7m2-q9xd-4hpw-…", | |
| 408 | − | "hint": "g1t-k7m2", | |
| 409 | − | "email": "ada@example.com", | |
| 410 | − | "kind": "account", | |
| 411 | − | "workspace": null, | |
| 412 | − | "status": "pending", | |
| 413 | − | "charged_to": "user", | |
| 414 | − | "invited_by": "syntaqx", | |
| 415 | − | "redeemed_by": null, | |
| 416 | − | "created_at": "2026-10-05T17:00:00.000Z", | |
| 417 | − | "expires_at": "2026-11-04T17:00:00.000Z", | |
| 418 | − | "redeemed_at": null, | |
| 419 | − | "revoked_at": null, | |
| 420 | − | "invitee": null, | |
| 421 | − | "role": null | |
| 422 | − | }, | |
| 423 | − | { | |
| 424 | − | "id": "inv_01kp1v3c4d5e6f7g8h9j0k1m2n", | |
| 425 | − | "code": null, | |
| 426 | − | "hint": "g1t-p3rt", | |
| 427 | − | "email": null, | |
| 428 | − | "kind": "account", | |
| 429 | − | "workspace": null, | |
| 430 | − | "status": "redeemed", | |
| 431 | − | "charged_to": "user", | |
| 432 | − | "invited_by": "syntaqx", | |
| 433 | − | "redeemed_by": "grace", | |
| 434 | − | "created_at": "2026-10-02T09:12:40.000Z", | |
| 435 | − | "expires_at": "2026-11-01T09:12:40.000Z", | |
| 436 | − | "redeemed_at": "2026-10-02T11:30:05.000Z", | |
| 437 | − | "revoked_at": null, | |
| 438 | − | "invitee": "grace", | |
| 439 | − | "role": null | |
| 440 | − | } | |
| 441 | − | ] | |
| 442 | − | }, | |
| 443 | − | "notes": "`allowance.limit` and `allowance.remaining` are null when you have no limit. A revoked or expired invite that was never used is not counted. `status` is `pending`, `awaiting_confirmation`, `awaiting_answer` (the account it made has yet to accept or decline the workspace in `workspace`), `redeemed`, `declined`, `expired` or `revoked`. Ask for more at hey@flagon.io with the subject `[g1t Invites]`. See [Invites](/guides/authentication/#invites)." | |
| 444 | − | }, | |
| 445 | − | "create_invite": { | |
| 446 | − | "request": { | |
| 447 | − | "email": "ada@example.com", | |
| 448 | − | "workspace": "acme-labs" | |
| 449 | − | }, | |
| 450 | − | "response": { | |
| 451 | − | "id": "inv_01kp2x7m8n9q0r1s2t3v4w5x6y", | |
| 452 | − | "code": "g1t-k7m2-q9xd-4hpw-…", | |
| 453 | − | "hint": "g1t-k7m2", | |
| 454 | − | "email": "ada@example.com", | |
| 455 | − | "kind": "account", | |
| 456 | − | "workspace": "acme-labs", | |
| 457 | − | "status": "pending", | |
| 458 | − | "charged_to": "user", | |
| 459 | − | "invited_by": "syntaqx", | |
| 460 | − | "redeemed_by": null, | |
| 461 | − | "created_at": "2026-10-05T17:00:00.000Z", | |
| 462 | − | "expires_at": "2026-11-04T17:00:00.000Z", | |
| 463 | − | "redeemed_at": null, | |
| 464 | − | "revoked_at": null, | |
| 465 | − | "invitee": null, | |
| 466 | − | "role": "member" | |
| 467 | − | }, | |
| 468 | − | "notes": "`workspace` brings the new account into a workspace you own: once it confirms its address it gets an invitation to join as a member, which it accepts or declines, and no workspace of its own is made for it. Leave `workspace` out and the new account gets a free workspace of its own. A workspace on the free plan cannot bring anyone in: `402` with `payment_required`, until it starts the g1t plan. `charge_workspace` is separate: it uses one of the invites g1t granted that workspace instead of one of yours, and works with or without `workspace`. Refused with `402` (`limit`) when you have no invites left, with `409` when you already have a pending invite for that address or it already has a g1t account, and with `403` for an agent's or a workspace's token. The code is returned in full; send people the link `https://g1t.sh/invite/<code>`." | |
| 469 | − | }, | |
| 470 | − | "revoke_invite": { | |
| 471 | − | "response": { | |
| 472 | − | "id": "inv_01kp2x7m8n9q0r1s2t3v4w5x6y", | |
| 473 | − | "code": null, | |
| 474 | − | "hint": "g1t-k7m2", | |
| 475 | − | "email": "ada@example.com", | |
| 476 | − | "kind": "account", | |
| 477 | − | "workspace": null, | |
| 478 | − | "status": "revoked", | |
| 479 | − | "charged_to": "user", | |
| 480 | − | "invited_by": "syntaqx", | |
| 481 | − | "redeemed_by": null, | |
| 482 | − | "created_at": "2026-10-05T17:00:00.000Z", | |
| 483 | − | "expires_at": "2026-11-04T17:00:00.000Z", | |
| 484 | − | "redeemed_at": null, | |
| 485 | − | "revoked_at": "2026-10-06T08:00:00.000Z", | |
| 486 | − | "invitee": null, | |
| 487 | − | "role": null | |
| 488 | − | } | |
| 489 | − | }, | |
| 490 | 386 | "list_workspace_invites": { | |
| 491 | 387 | "response": [ | |
| 492 | 388 | { | |
| ⋯ | |||
| 497 | 393 | "kind": "account", | |
| 498 | 394 | "workspace": "acme-labs", | |
| 499 | 395 | "status": "pending", | |
| 500 | − | "charged_to": "workspace", | |
| 501 | 396 | "invited_by": "syntaqx", | |
| 502 | 397 | "redeemed_by": null, | |
| 503 | 398 | "created_at": "2026-10-05T17:00:00.000Z", | |
| ⋯ | |||
| 515 | 410 | "kind": "workspace", | |
| 516 | 411 | "workspace": "acme-labs", | |
| 517 | 412 | "status": "pending", | |
| 518 | − | "charged_to": "none", | |
| 519 | 413 | "invited_by": "syntaqx", | |
| 520 | 414 | "redeemed_by": null, | |
| 521 | 415 | "created_at": "2026-10-05T17:00:00.000Z", | |
| ⋯ | |||
| 540 | 434 | "kind": "workspace", | |
| 541 | 435 | "workspace": "acme-labs", | |
| 542 | 436 | "status": "pending", | |
| 543 | − | "charged_to": "none", | |
| 544 | 437 | "invited_by": "syntaqx", | |
| 545 | 438 | "redeemed_by": null, | |
| 546 | 439 | "created_at": "2026-10-05T17:00:00.000Z", | |
| ⋯ | |||
| 561 | 454 | "kind": "account", | |
| 562 | 455 | "workspace": "acme-labs", | |
| 563 | 456 | "status": "revoked", | |
| 564 | − | "charged_to": "workspace", | |
| 565 | 457 | "invited_by": "syntaqx", | |
| 566 | 458 | "redeemed_by": null, | |
| 567 | 459 | "created_at": "2026-10-05T17:00:00.000Z", | |
| 214 | 214 | through::<g1t_contracts::accounts::AccountEmails>(op, sent) | |
| 215 | 215 | } | |
| 216 | 216 | Op::ConfirmEmail => through::<g1t_contracts::accounts::EmailConfirmed>(op, sent), | |
| 217 | − | Op::ListInvites => through::<g1t_contracts::identity::InvitesOverview>(op, sent), | |
| 218 | − | Op::CreateInvite | Op::RevokeInvite | Op::InviteMember | Op::RevokeWorkspaceInvite => { | |
| 217 | + | Op::InviteMember | Op::RevokeWorkspaceInvite => { | |
| 219 | 218 | through::<g1t_contracts::identity::Invite>(op, sent) | |
| 220 | 219 | } | |
| 221 | 220 | Op::ListWorkspaceInvites => through::<Vec<g1t_contracts::identity::Invite>>(op, sent), |
| 52 | 52 | route("POST", "/user/emails/confirm", Op::ConfirmEmail, &[]), | |
| 53 | 53 | route("DELETE", "/user/emails/:email", Op::RemoveEmail, &[]), | |
| 54 | 54 | route("PATCH", "/user/email-settings", Op::UpdateEmailSettings, &[]), | |
| 55 | − | route("GET", "/user/invites", Op::ListInvites, &[]), | |
| 56 | − | route("POST", "/user/invites", Op::CreateInvite, &[]), | |
| 57 | − | route("DELETE", "/user/invites/:id", Op::RevokeInvite, &[]), | |
| 58 | 55 | // Invitations to workspaces waiting for your answer. | |
| 59 | 56 | route("GET", "/user/invitations", Op::ListInvitations, &[]), | |
| 60 | 57 | route("POST", "/user/invitations/:id/accept", Op::AcceptInvitation, &[]), |
| 578 | 578 | Tool { | |
| 579 | 579 | name: "account", | |
| 580 | 580 | title: "Your account", | |
| 581 | − | description: "Who this token acts as and its workspaces (`whoami`), your email addresses, your invites, and invitations to workspaces and repositories waiting for you.", | |
| 581 | + | description: "Who this token acts as and its workspaces (`whoami`), your email addresses, and invitations to workspaces and repositories waiting for you.", | |
| 582 | 582 | default_action: Some("whoami"), | |
| 583 | 583 | actions: &[ | |
| 584 | 584 | a("whoami", Op::Whoami, "Who the token acts as, and its workspaces"), | |
| ⋯ | |||
| 587 | 587 | a("confirm_email", Op::ConfirmEmail, "Confirm an address with the code from its email"), | |
| 588 | 588 | a("remove_email", Op::RemoveEmail, "Remove an address"), | |
| 589 | 589 | a("update_email_settings", Op::UpdateEmailSettings, "Primary, backup and privacy"), | |
| 590 | − | a("list_invites", Op::ListInvites, "Your invites to g1t"), | |
| 591 | − | a("create_invite", Op::CreateInvite, "Make an invite"), | |
| 592 | − | a("revoke_invite", Op::RevokeInvite, "Revoke one"), | |
| 593 | 590 | a("list_workspace_invitations", Op::ListInvitations, "Invitations to workspaces for you"), | |
| 594 | 591 | a("accept_workspace_invitation", Op::AcceptInvitation, "Accept one and join"), | |
| 595 | 592 | a("decline_workspace_invitation", Op::DeclineInvitation, "Decline one"), | |
| 489 | 489 | ||
| 490 | 490 | ## Accounts, status and self-hosting | |
| 491 | 491 | ||
| 492 | − | ### Sign-up needs an invite | |
| 493 | − | ||
| 494 | − | g1t is invite-only for now. See [Invites](/guides/authentication/#invites). | |
| 495 | − | **Status.** Opening sign-up is planned. | |
| 496 | − | ||
| 497 | 492 | ### Tokens for one workspace you belong to | |
| 498 | 493 | ||
| 499 | 494 | A personal access token can be made for one workspace only when you are a |
| 1 | 1 | --- | |
| 2 | 2 | title: Accounts and authentication | |
| 3 | − | description: Accounts, invites, email addresses, confirming them, two-factor authentication and recovery codes, personal access tokens and their permissions and scopes, a workspace's rules for tokens, OAuth, signing in from a tool, password reset, your security log and deleting your account. | |
| 3 | + | description: Creating an account, invitations, email addresses, confirming them, two-factor authentication and recovery codes, personal access tokens and their permissions and scopes, a workspace's rules for tokens, OAuth, signing in from a tool, password reset, your security log and deleting your account. | |
| 4 | 4 | --- | |
| 5 | 5 | ||
| 6 | 6 | ## Creating an account | |
| 7 | 7 | ||
| 8 | − | g1t is invite-only for now: to make an account you need an | |
| 9 | − | [invite](#invites). Open the link in your invite, or enter its code at | |
| 10 | − | [g1t.sh/register](https://g1t.sh/register). Without one, ask for access | |
| 11 | − | on the same page. | |
| 8 | + | Anyone can make an account at [g1t.sh/register](https://g1t.sh/register), | |
| 9 | + | with an email address and a password or with **Continue with GitHub**. No | |
| 10 | + | invite is needed. If someone invited you into a workspace or onto a | |
| 11 | + | repository, open the link in their invitation instead: it signs you up and | |
| 12 | + | takes you to what you were invited to (see [invites](#invites)). | |
| 12 | 13 | ||
| 13 | 14 | Usernames are letters, digits and single hyphens, 1 to 39 characters, not | |
| 14 | 15 | starting or ending with a hyphen. They keep the case you type: choose | |
| ⋯ | |||
| 44 | 45 | | Profile | [`/settings/profile`](https://g1t.sh/settings/profile) | Your picture, and your [public profile](/guides/workspaces/#profiles): name, pronouns, bio, location, website and time zone. | | |
| 45 | 46 | | Emails | [`/settings/emails`](https://g1t.sh/settings/emails) | Your [email addresses](#email-addresses), the backup address, and [keeping your address private](#keeping-your-address-private). | | |
| 46 | 47 | | Notifications | [`/settings/notifications`](https://g1t.sh/settings/notifications) | [Sounds and do not disturb](/guides/chat/#sounds-and-do-not-disturb), [pop-ups and browser notifications](/guides/chat/#notifications), and [what you are emailed for and how you watch repositories](/guides/notifications/#settings). | | |
| 47 | − | | Invites to g1t | [`/settings/invites`](https://g1t.sh/settings/invites) | [Making, copying and revoking invites to g1t](#making-invites), while g1t is invite-only; after that, the invites you made. | | |
| 48 | 48 | | SSH keys | [`/settings/keys`](https://g1t.sh/settings/keys) | Public keys for [git over SSH](/guides/git/#ssh), each with when it was added and last used. | | |
| 49 | 49 | | Access tokens | [`/settings/tokens`](https://g1t.sh/settings/tokens) | Your [personal access tokens](#access-tokens): their permissions, where they reach, and when they expire. | | |
| 50 | 50 | | Integrations | [`/settings/integrations`](https://g1t.sh/settings/integrations) | [Your own integrations](/guides/integrations/#workspace-and-personal): what you have connected for yourself, in every workspace, and what is coming. | | |
| ⋯ | |||
| 129 | 129 | ||
| 130 | 130 | ## Invites | |
| 131 | 131 | ||
| 132 | − | There are two kinds of invite, and they do different things: | |
| 133 | − | ||
| 134 | − | | | Invite to g1t | Invite to a workspace | | |
| 135 | − | | --- | --- | --- | | |
| 136 | − | | Made from | [Settings → Invites](https://g1t.sh/settings/invites), your own | **Invite** on the workspace's **Members** or **Invitations** page, by its owners | | |
| 137 | − | | What it gives | One new account. It adds them to no workspace: the account gets a workspace of its own | An invitation to join that workspace, which they accept or decline | | |
| 138 | − | | Someone without an account | Makes their account with it | Makes their account with it too, while g1t is invite-only, then answers the invitation | | |
| 139 | − | | Someone already on g1t | Nothing: they have an account | The invitation, in their notifications and by email | | |
| 140 | − | | Exists | Only while g1t is invite-only | Always | | |
| 141 | − | | What its page and email say | "@syntaqx invited you to g1t" | "@syntaqx invited you to join Flagon, Inc. on g1t" | | |
| 132 | + | Anyone can sign up without an invite. Invites are how people already on | |
| 133 | + | g1t bring someone in: | |
| 142 | 134 | ||
| 143 | − | So you can invite someone to g1t without inviting them into any | |
| 144 | − | workspace; an invite to g1t only adds them to a workspace when you tick | |
| 145 | − | **Also invite them to a workspace** (see [making invites](#making-invites)). | |
| 135 | + | - an owner's [invitation into a workspace](#inviting-someone-into-a-workspace), | |
| 136 | + | by username or by email address; | |
| 137 | + | - an [invitation to collaborate on a repository](/guides/access-and-roles/), | |
| 138 | + | by username or by email address. | |
| 146 | 139 | ||
| 147 | − | While g1t is invite-only, every new account needs an invite code, such as | |
| 148 | − | `g1t-k7m2-q9xd-…`. People already on g1t make them, and g1t sends them to | |
| 149 | − | people who [asked for access](#asking-for-access). An invite: | |
| 140 | + | Invited by username, the account gets the invitation in its notifications | |
| 141 | + | and by email. Invited by an address that has no g1t account yet, the email | |
| 142 | + | carries an invite code, such as `g1t-k7m2-q9xd-…`, in a link to | |
| 143 | + | `g1t.sh/invite/<code>`. That invite: | |
| 150 | 144 | ||
| 151 | − | - works once, for one new account; | |
| 145 | + | - works once, for the address it was sent to; | |
| 152 | 146 | - works for 30 days; | |
| 153 | − | - when it was made for an email address, works only with that address; | |
| 154 | − | - can be revoked by whoever made it until it is used, and after that until | |
| 155 | − | the new account [confirms its email address](#confirming-your-email-address). | |
| 147 | + | - can be revoked by whoever sent it (or the workspace's owners) until it is | |
| 148 | + | used, and after that until the new account | |
| 149 | + | [confirms its email address](#confirming-your-email-address). | |
| 156 | 150 | ||
| 157 | 151 | ### Using an invite | |
| 158 | 152 | ||
| ⋯ | |||
| 197 | 191 | invite is revoked or expires, or its workspace is deleted, before you | |
| 198 | 192 | confirm, your address is confirmed all the same and g1t tells you the | |
| 199 | 193 | invite no longer applies: ask whoever invited you to invite you again. A | |
| 200 | − | code typed at [g1t.sh/register](https://g1t.sh/register) goes to the | |
| 201 | − | same page. | |
| 194 | + | link to [g1t.sh/register](https://g1t.sh/register) with a good invite code | |
| 195 | + | goes to the same page. | |
| 202 | 196 | ||
| 203 | 197 | An expired, revoked or used invite says which, and who sent it, so you | |
| 204 | − | can ask them for a new one; or ask for access from the same page. | |
| 198 | + | can ask them for a new one; or [sign up](https://g1t.sh/register) without | |
| 199 | + | it. | |
| 205 | 200 | ||
| 206 | 201 | ### Invites from your inbox | |
| 207 | 202 | ||
| 208 | − | When g1t emails an invite to an address (an invite you make for someone, | |
| 209 | − | an owner's invite into a workspace or a repository, or an approved | |
| 210 | − | [request for access](#asking-for-access)), the link in that email carries a | |
| 203 | + | When g1t emails an invite to an address (an owner's invitation into a | |
| 204 | + | workspace, or an invitation onto a repository), the link in that email carries a | |
| 211 | 205 | `proof` that only the email has: `g1t.sh/invite/<code>?proof=…`. Opening | |
| 212 | 206 | the link shows that you can read that inbox, so: | |
| 213 | 207 | ||
| ⋯ | |||
| 218 | 212 | names is a [workspace invitation](#workspace-invitations) you accept or | |
| 219 | 213 | decline straight away, since nobody joins a workspace without saying yes. | |
| 220 | 214 | ||
| 221 | − | Anything else confirms the address the usual way, after you sign up: the | |
| 222 | − | code typed at [g1t.sh/register](https://g1t.sh/register), an invite link | |
| 223 | − | copied from **Settings → Invites** (whoever made the invite sees the code, | |
| 224 | − | never the proof), an invite made for anyone with the link, or an invite | |
| 225 | − | email sent before this existed. The proof is tied to one invite and its | |
| 215 | + | Anything else confirms the address the usual way, after you sign up: an | |
| 216 | + | invite link copied from the workspace's **Invitations** page (whoever sent | |
| 217 | + | the invite sees the code, never the proof), or an invite email sent before | |
| 218 | + | this existed. The proof is tied to one invite and its | |
| 226 | 219 | address, and stops working when the invite is used, revoked or expires. | |
| 227 | − | ||
| 228 | − | ### Invite links for a group | |
| 229 | − | ||
| 230 | − | g1t sometimes hands one link to a group: an event's judges, readers of a | |
| 231 | − | post, a community. It looks like | |
| 232 | − | `https://g1t.sh/register?invite=g1t-k7m2-…` and opens sign-up with the | |
| 233 | − | code filled in and the group named above the form, such as **Invited as | |
| 234 | − | part of Launch week judges**. | |
| 235 | − | ||
| 236 | − | - **It makes your own account.** Each person who uses it gets a new | |
| 237 | − | account, and then makes their own workspace. It does not add you to | |
| 238 | − | anyone else's workspace; once you are in, a workspace's owners can add | |
| 239 | − | you from its **Members** page. | |
| 240 | − | - **It may be for some email domains only.** When it is, the email field | |
| 241 | − | says which, such as `example.com`, and sign-up takes only an address | |
| 242 | − | there. Use your address at that organization; you confirm it like any | |
| 243 | − | other. | |
| 244 | − | - **It works a set number of times, until a set day.** Once every place | |
| 245 | − | is taken, or the day has passed, or g1t has stopped it, the link gets | |
| 246 | − | the same answer as any invite that cannot be used. Ask whoever shared | |
| 247 | − | it, or [ask for access](#asking-for-access). | |
| 248 | − | ||
| 249 | − | Using the link spends one place in the same step that makes your account, | |
| 250 | − | so two people signing up at the same moment can never take more places | |
| 251 | − | than it has. Anyone with an account can still [make invites](#making-invites) | |
| 252 | − | of their own; group links are made by g1t staff only. | |
| 253 | − | ||
| 254 | − | ### Making invites | |
| 255 | − | ||
| 256 | − | These are invites to g1t. They let one person make an account, and add | |
| 257 | − | them to no workspace unless you say so. | |
| 258 | − | ||
| 259 | − | 1. Open [Settings → Invites](https://g1t.sh/settings/invites) (**Invites | |
| 260 | − | to g1t** in your settings and account menu). | |
| 261 | − | 2. Optionally enter the email address of the person you are inviting. | |
| 262 | − | With one, g1t emails them the invite, and only that address can use it. | |
| 263 | − | Without one, anyone with the link can, once. | |
| 264 | − | 3. Optionally tick **Also invite them to a workspace**, then choose the | |
| 265 | − | workspace and the role (**Member** or **Owner**) they are invited with. | |
| 266 | − | It is off to start with, and no workspace is chosen for you, not even | |
| 267 | − | the one you are in. | |
| 268 | − | 4. Select **Create invite**, then copy the link. | |
| 269 | − | ||
| 270 | − | Left unticked, the invite is to g1t only: the new account gets a | |
| 271 | − | [workspace of its own](#your-first-workspace). Ticked, the new account | |
| 272 | − | gets a [workspace invitation](#workspace-invitations) to the workspace you | |
| 273 | − | chose once its address is confirmed, and is not given a workspace of its | |
| 274 | − | own. The list of workspaces holds the ones you can add members to: the ones | |
| 275 | − | you own that are on the g1t plan. A workspace on the free plan cannot add | |
| 276 | − | people, so it is not offered, and the form says so when it is the one you | |
| 277 | − | are in. | |
| 278 | 220 | ||
| 279 | − | To bring someone into a workspace, you do not need an invite to g1t: | |
| 280 | − | invite them from the workspace's **Members** page, | |
| 281 | − | `g1t.sh/<workspace>/-/members`, instead (see | |
| 282 | − | [inviting someone into a workspace](#inviting-someone-into-a-workspace)). | |
| 283 | − | Settings → Invites links to the Members pages of the workspaces you own. | |
| 284 | − | ||
| 285 | − | Once anyone can sign up for g1t, there are no invites to g1t to make: | |
| 286 | − | Settings → Invites keeps only the list of invites you already made, and | |
| 287 | − | says that anyone can sign up now and that workspace invitations live on | |
| 288 | − | each workspace's Invitations page. With no invites made, the page is not listed | |
| 289 | − | in your settings or account menu. | |
| 290 | − | ||
| 291 | − | Each person can have **5** invites out at a time. Pending and used invites | |
| 292 | − | count; an invite you revoke, or one that expires before anyone uses it, | |
| 293 | − | comes back to you. The list under the form shows each invite's state: | |
| 294 | − | pending, confirming their email (used to sign up by someone who has not | |
| 295 | − | confirmed their address yet), waiting for them to accept (the account is | |
| 296 | − | made and confirmed, and the workspace invitation waits for its answer), | |
| 297 | − | joined (with the username of who joined), declined, expired or revoked. You | |
| 298 | − | must confirm your email before you can make invites. An agent's token and | |
| 299 | − | a workspace's token cannot make them. | |
| 300 | − | ||
| 301 | 221 | ### Inviting someone into a workspace | |
| 302 | 222 | ||
| 303 | 223 | An owner can invite someone into a workspace from its **Members and | |
| ⋯ | |||
| 308 | 228 | to accept or decline. When an address has no g1t account, the invitation | |
| 309 | 229 | also lets it make one first, and the invitation is answered once the | |
| 310 | 230 | account's address is confirmed (at once when it was made from the invite | |
| 311 | − | email's link). While g1t is invite-only, that uses one invite: one of the | |
| 312 | − | workspace's shared invites when it has any, otherwise one of yours. Once | |
| 313 | − | anyone can sign up, it costs nothing. Inviting someone who is already on | |
| 314 | − | g1t never costs anything. | |
| 231 | + | email's link). Inviting someone costs nothing either way. | |
| 315 | 232 | ||
| 316 | 233 | ### Workspace invitations | |
| 317 | 234 | ||
| ⋯ | |||
| 336 | 253 | ||
| 337 | 254 | - An account whose invite brings it into a workspace gets the invitation | |
| 338 | 255 | to it, and no workspace of its own. | |
| 339 | − | - Every other account (signed up with a password, with GitHub, from a | |
| 340 | − | shared invite link or an invite from g1t staff, or with an invite that | |
| 341 | − | names no workspace) gets a workspace of its own, named for its username, | |
| 342 | − | on the free plan. Rename it or start the plan on it whenever you like. | |
| 256 | + | - Every other account (signed up with a password or with GitHub, or with | |
| 257 | + | an invite that names no workspace, such as one onto a repository) gets a | |
| 258 | + | workspace of its own, named for its username, on the free plan. Rename it or start the plan on it whenever you like. | |
| 343 | 259 | ||
| 344 | 260 | Signed in without any workspace (you declined an invitation, or left the | |
| 345 | 261 | only workspace you were in), g1t shows **Create your workspace or ask to | |
| 346 | 262 | join one** in place of Mission control: the invitations waiting for you, if | |
| 347 | 263 | any, and the form to create a workspace. To join a team already on g1t, | |
| 348 | 264 | ask one of its owners to invite you by your username. | |
| 349 | − | ||
| 350 | − | ### Need more invites? | |
| 351 | − | ||
| 352 | − | Write to [hey@flagon.io](mailto:hey@flagon.io?subject=%5Bg1t%20Invites%5D%20) | |
| 353 | − | with the subject `[g1t Invites]` and say who you would like to bring. g1t | |
| 354 | − | can give more invites to you, or to a workspace, whose owners then share | |
| 355 | − | them. Invites given to a workspace appear under | |
| 356 | − | [Settings → Invites](https://g1t.sh/settings/invites) for | |
| 357 | − | each of its owners, as a choice of whose invites to use. | |
| 358 | − | ||
| 359 | − | ### Asking for access | |
| 360 | 265 | ||
| 361 | − | Without an invite, [g1t.sh/register](https://g1t.sh/register) asks for your | |
| 362 | − | email address and, if you like, what you will build. g1t emails that | |
| 363 | − | address once to confirm you are on the list, and staff see the request | |
| 364 | − | straight away. When they approve it, the invite comes to the same address, | |
| 365 | − | sometimes with a note, and its link opens sign-up with the address filled | |
| 366 | − | in. There is no fixed date: g1t opens up a few people at a time. Asking | |
| 367 | − | again with the same address updates your request without another email; it | |
| 368 | − | does not move you down the list. | |
| 369 | − | ||
| 370 | 266 | ### Invites through the API | |
| 371 | 267 | ||
| 372 | 268 | | Route | MCP tool and action | What it does | | |
| 373 | 269 | | --- | --- | --- | | |
| 374 | − | | [`GET /user/invites`](/reference/api/invites/list-invites/) | `account` `list_invites` | Your invites and how many you have left | | |
| 375 | − | | [`POST /user/invites`](/reference/api/invites/create-invite/) | `account` `create_invite` | Make an invite, optionally for one `email`; with `workspace` (a slug), the new account is invited to that workspace | | |
| 376 | − | | [`DELETE /user/invites/{id}`](/reference/api/invites/revoke-invite/) | `account` `revoke_invite` | Revoke a pending invite, or one whose new account has not confirmed its address | | |
| 377 | 270 | | [`POST /workspaces/{workspace}/invitations`](/reference/api/invites/invite-member/) | `workspace` `invite_member` | Invite a `username` or an `email` into a workspace, with a `role`. Owners only. | | |
| 378 | 271 | | [`GET /user/invitations`](/reference/api/invites/list-invitations/) | `account` `list_workspace_invitations` | The workspace invitations waiting for your answer | | |
| 379 | 272 | | [`POST /user/invitations/{id}/accept`](/reference/api/invites/accept-invitation/) | `account` `accept_workspace_invitation` | Join the invitation's workspace with its role | | |
| ⋯ | |||
| 420 | 313 | - **The MCP server** answers `403` with the same message. | |
| 421 | 314 | - **Git** over HTTPS refuses pushes and fetches with your credentials, with | |
| 422 | 315 | the same message. Package registries treat them as wrong credentials. | |
| 423 | − | - You cannot create a workspace, answer the invitation your invite brought, make | |
| 424 | − | invites or tokens, or approve a tool's sign-in. | |
| 316 | + | - You cannot create a workspace, answer the invitation your invite brought, | |
| 317 | + | invite anyone, make tokens, or approve a tool's sign-in. | |
| 425 | 318 | ||
| 426 | 319 | You cannot make a token before you confirm, so the API and MCP refusals | |
| 427 | 320 | matter only for an account that made one before this rule existed. | |
| ⋯ | |||
| 1242 | 1135 | ||
| 1243 | 1136 | ## Too many attempts | |
| 1244 | 1137 | ||
| 1245 | − | g1t counts wrong passwords, on the sign-in page, for git over HTTPS and | |
| 1138 | + | g1t counts sign-ups with a password from each network: after **5** in an | |
| 1139 | + | hour, [g1t.sh/register](https://g1t.sh/register) answers "Too many accounts | |
| 1140 | + | were made from your network in the last hour" until the hour is up. A form | |
| 1141 | + | with a mistake in it (a username that cannot be used, an address that is | |
| 1142 | + | not one, a short password) is not counted. Signing up with GitHub is not | |
| 1143 | + | counted this way: it needs a GitHub account with a verified address. | |
| 1144 | + | ||
| 1145 | + | g1t also counts wrong passwords, on the sign-in page, for git over HTTPS and | |
| 1246 | 1146 | when confirming it is you, against the account and against where they come | |
| 1247 | 1147 | from. After 10 wrong passwords for one account in an hour, or 30 from one | |
| 1248 | 1148 | place, g1t stops checking passwords for it for a minute, then twice as long | |
| 28 | 28 | - **Password**: none. Sign in with GitHub, or set a password later with | |
| 29 | 29 | [Forgot your password](https://g1t.sh/forgot). | |
| 30 | 30 | ||
| 31 | − | g1t is invite-only for now. To create an account with GitHub, open the | |
| 32 | − | invite link you were given and choose **Continue with GitHub** there, or | |
| 33 | − | enter your invite code when g1t asks for it after GitHub. Signing in to an | |
| 34 | − | account you already have needs no invite. | |
| 31 | + | Anyone can create an account with GitHub: choose **Continue with GitHub** | |
| 32 | + | on [g1t.sh/register](https://g1t.sh/register). If someone invited you into | |
| 33 | + | a workspace or onto a repository, open their invite link and choose | |
| 34 | + | **Continue with GitHub** there instead, so the new account gets the | |
| 35 | + | invitation. | |
| 35 | 36 | ||
| 36 | 37 | Signing in with GitHub does not start a trial or give your workspace | |
| 37 | 38 | compute. That works as it does for any account: see |
| 162 | 162 | | `MAILPIT_PORT` | `8025` | The port of the Mailpit inbox | | |
| 163 | 163 | | `MAIL_FROM` | `g1t <noreply@localhost>` | The sender of g1t's email | | |
| 164 | 164 | | `MAIL_URL` | `http://mailpit:8025` | The Mailpit server g1t sends mail through | | |
| 165 | − | | `REGISTRATION_MODE` | `open` | `open`: anyone can make an account. `invite`: every new account needs an [invite](/guides/authentication/#invites), as on g1t.sh. | | |
| 166 | − | | `INVITES_PER_USER` | `5` | How many invites each person can have out, while `REGISTRATION_MODE` is `invite` | | |
| 167 | − | | `WAITLIST_NOTIFY_EMAIL` | (none) | Where a summary of new access requests goes, at most every 15 minutes. Empty sends none; requests still wait for you in the database. | | |
| 168 | 165 | | `S3_ENDPOINT`, `S3_BUCKET`, `S3_REGION`, `S3_ACCESS_KEY_ID`, `S3_SECRET_ACCESS_KEY` | the bundled RustFS, bucket `g1t-packages` | Where packages' files are kept: any S3-compatible store. Change the two keys before first start; RustFS is made with them. | | |
| 169 | 166 | | `S3_PUBLIC_ENDPOINT` | (none) | The store's address as clients reach it. When set, large layers are downloaded from it directly with a signed URL. | | |
| 170 | 167 | | `PACK_S3_BUCKET` | `g1t-git-packs` | The bucket on the same store that packs for fresh clones are kept in, so the next clone of the same commit is not built again. The bundled store deletes packs after 7 days, and uploads left unfinished after a day; on another store, give the bucket a lifecycle rule that does the same. | | |
| ⋯ | |||
| 174 | 171 | | `BACKUP_S3_BUCKET` | `g1t-backups` | The bucket on the same store that nightly repository backups (a `git bundle` of each repository whose branches or tags changed) are kept in. The bundles are cut by g1t's runner, which this installation does not run yet, so the bucket stays empty for now: copy the volumes, as below. | | |
| 175 | 172 | | `STATUS_PORT` | `8788` | The port the status page is published on | | |
| 176 | 173 | | `STATUS_PROBE_REPO` | (none) | A public repository, `workspace/repo`, whose branches the status page lists every minute as a clone would. Empty: git is not checked. | | |
| 177 | − | | `INVITE_STAFF_WORKSPACES` | (none) | Workspace slugs, comma separated, whose owners can make invites without a limit. Set it to your own workspace before you switch to `invite`, so someone can invite the first people. | | |
| 178 | 174 | | `PHONE_PUSH` | `on` | `off`: send [the phone app](#the-phone-app) no notifications, so their words never pass through Expo's push service. Browser and desktop notifications are not affected. | | |
| 179 | 175 | ||
| 180 | 176 | ## The phone app | |
| 368 | 368 | without saying yes: an owner invites people, and each person accepts or | |
| 369 | 369 | declines. | |
| 370 | 370 | ||
| 371 | − | This is an invitation to join one workspace. It is not the same as an | |
| 372 | − | invite to g1t, which only lets someone make an account: | |
| 373 | − | ||
| 374 | − | | | Invite to a workspace | Invite to g1t | | |
| 375 | − | | --- | --- | --- | | |
| 376 | − | | Where | **Invite** on the workspace's **Members** or **Invitations** page | [Settings → Invites](https://g1t.sh/settings/invites) | | |
| 377 | − | | What they get | An invitation to join the workspace, to accept or decline | One new account, in no workspace but its own | | |
| 378 | − | | Without an account | The invitation lets them sign up first, while g1t is invite-only | It lets them sign up | | |
| 379 | − | | When | Always | Only while g1t is invite-only | | |
| 380 | − | ||
| 381 | − | To invite someone to g1t without adding them to your workspace, use | |
| 382 | − | [Settings → Invites](/guides/authentication/#making-invites). | |
| 371 | + | Anyone can make a g1t account without an invite, so to bring someone in | |
| 372 | + | you invite them to the workspace; someone without an account signs up from | |
| 373 | + | the invitation. | |
| 383 | 374 | ||
| 384 | 375 | On the workspace's **Members** page, `g1t.sh/<workspace>/-/members` | |
| 385 | 376 | (**Workspace → Access → Members** in the sidebar), or on **Invitations** | |
| ⋯ | |||
| 404 | 395 | - **By email address**: g1t emails an invite that only that address can | |
| 405 | 396 | use. With a g1t account, it is a workspace invitation like the one above | |
| 406 | 397 | and costs nothing. Without one, the invitation also lets them make the | |
| 407 | − | account first; while g1t is invite-only that uses one of the workspace's | |
| 408 | − | granted invites, or else one of yours (see | |
| 409 | − | [invites](/guides/authentication/#invites)), and once anyone can sign up | |
| 410 | − | it costs nothing. The new account is then invited to the workspace, and | |
| 411 | − | joins when it accepts. The page never says which it was. | |
| 398 | + | account first, and costs nothing (see | |
| 399 | + | [invites](/guides/authentication/#invites)). The new account is then | |
| 400 | + | invited to the workspace, and joins when it accepts. The page never says which it was. | |
| 412 | 401 | ||
| 413 | 402 | The email names you and the workspace and links to the invite's page. | |
| 414 | 403 | Someone new signs up right there, with the invited address filled in; once | |
| 24 | 24 | ||
| 25 | 25 | 1. **Create an account and a workspace** | |
| 26 | 26 | ||
| 27 | − | [Sign up](https://g1t.sh/register) with your invite (g1t is invite-only | |
| 28 | − | for now; see [invites](/guides/authentication/#invites)) and confirm your | |
| 27 | + | [Sign up](https://g1t.sh/register) (or open the invite link someone sent | |
| 28 | + | you; see [invites](/guides/authentication/#invites)) and confirm your | |
| 29 | 29 | email with the code g1t sends it (or the link in the same email). Then create a | |
| 30 | 30 | **workspace**: it holds your channels, agents and repositories. See | |
| 31 | 31 | [workspaces](/guides/workspaces/). |
| 230 | 230 | | [Workspaces](/reference/api/workspaces/create-workspace/) | Creating a workspace. | | |
| 231 | 231 | | [Notifications](/reference/api/notifications/list-notifications/) | Your notifications: their threads, why you were told of each, marking them read, done, saved or snoozed, and what you subscribe to and watch. See [notifications](/guides/notifications/). | | |
| 232 | 232 | | [Billing](/reference/api/billing/get-usage/) | A workspace's usage by product, project and day, its budget, its AI credit, its invoices and its [AI Gateway](/guides/ai-gateway/) requests. See [usage and billing](/guides/usage-and-billing/). | | |
| 233 | − | | [Invites](/reference/api/invites/list-invites/) | Your invites while g1t is invite-only, and inviting people into a workspace by email. | | |
| 233 | + | | [Invites](/reference/api/invites/list-workspace-invites/) | Inviting people into a workspace by username or email, and answering the invitations sent to you. | | |
| 234 | 234 | | [Repositories](/reference/api/repositories/list-repos/) | A repository, how it handles pull requests, and its timeline. | | |
| 235 | 235 | | [Access](/reference/api/access/list-collaborators/) | Who has which role on a repository, invitations, outside collaborators, and a workspace's base permission. | | |
| 236 | 236 | | [Secret scanning](/reference/api/secret-scanning/list-secret-scanning-alerts/) | Secrets found in pushes and history, where each one is, bypassing push protection and reviewing bypass requests, validity checks, and custom patterns. See [secret protection](/guides/security/secret-protection/). | |
| 818 | 818 | ||
| 819 | 819 | ## `account` | |
| 820 | 820 | ||
| 821 | − | Who the token acts as and its workspaces, your email addresses, your | |
| 822 | − | invites while g1t is [invite-only](/guides/authentication/#invites), and | |
| 823 | − | invitations to workspaces and repositories waiting for you. `whoami` is the default | |
| 821 | + | Who the token acts as and its workspaces, your email addresses, and | |
| 822 | + | [invitations](/guides/authentication/#invites) to workspaces and | |
| 823 | + | repositories waiting for you. `whoami` is the default | |
| 824 | 824 | action, and needs no scope. An agent's token and a workspace's token cannot | |
| 825 | − | use the email and invite actions. An account that has not confirmed its | |
| 825 | + | use the email and invitation actions. An account that has not confirmed its | |
| 826 | 826 | email address gets `403` from every tool until it does; see | |
| 827 | 827 | [until you confirm](/guides/authentication/#until-you-confirm). | |
| 828 | 828 | ||
| ⋯ | |||
| 834 | 834 | | [`confirm_email`](/reference/api/accounts/confirm-email/) | Confirm an address with the six-digit code from its email. See [confirming your email address](/guides/authentication/#confirming-your-email-address). | `code` | `account:write` | | |
| 835 | 835 | | [`remove_email`](/reference/api/accounts/remove-email/) | Remove an address; never the primary or the last confirmed one. | `email`, `password` | `account:write` | | |
| 836 | 836 | | [`update_email_settings`](/reference/api/accounts/update-email-settings/) | Change `primary` or `backup` (with `password`), `private_email` or `block_private_pushes`. See [email addresses](/guides/authentication/#email-addresses). | None | `account:write` | | |
| 837 | − | | [`list_invites`](/reference/api/invites/list-invites/) | Your invites, newest first, and how many you have left. | None | `account:read` | | |
| 838 | − | | [`create_invite`](/reference/api/invites/create-invite/) | Make an invite; with `email`, only that address can use it and it is emailed there. With `workspace`, the new account is invited to that workspace (one you own, on the g1t plan) once it confirms its address, instead of getting a workspace of its own. With `charge_workspace`, use that workspace's granted invites instead of yours. | None | `account:write` | | |
| 839 | − | | [`revoke_invite`](/reference/api/invites/revoke-invite/) | Revoke a pending invite; it comes back to whoever it was charged to. | `id` | `account:write` | | |
| 840 | 837 | | [`list_workspace_invitations`](/reference/api/invites/list-invitations/) | The invitations to workspaces waiting for your answer, each with its `workspace`, the `role` it gives and who sent it. | None | `account:read` | | |
| 841 | 838 | | [`accept_workspace_invitation`](/reference/api/invites/accept-invitation/) | Accept one; you join the workspace at once with its role. | `id` | `account:write` | | |
| 842 | 839 | | [`decline_workspace_invitation`](/reference/api/invites/decline-invitation/) | Decline one; whoever sent it is told. | `id` | `account:write` | | |
Binary or large file; its contents are not shown.
Comments
Sign in to comment.