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.
| Merge workspace invitations: nobody joins a workspace without saying yes, people are found by username, your own invites can bring someone in, and nobody is left without a workspace (identity 0040) | 1 | import assert from "node:assert/strict"; |
| 2 | import { test } from "node:test"; | |
| 3 | ||
| 4 | import { pageOf } from "./confirm-gate.ts"; | |
| 5 | import { NO_WORKSPACE_PATH, hasNoWorkspace, workspaceGate } from "./workspace-gate.ts"; | |
| 6 | ||
| 7 | const nobody = { kind: "user", verified: true, workspaces: [], grants: [], held: [] }; | |
| 8 | const member = { ...nobody, workspaces: [{ slug: "acme", role: "member" }] }; | |
| 9 | ||
| 10 | test("someone with no workspace is sent to make one or answer an invitation, never to Mission control", () => { | |
| 11 | assert.equal(workspaceGate("/", "", nobody), NO_WORKSPACE_PATH); | |
| 12 | // A data request for Mission control is gated too, so a client navigation never shows it. | |
| 13 | assert.equal(workspaceGate(pageOf("/_root.data"), "?_routes=routes%2Fhome", nobody), NO_WORKSPACE_PATH); | |
| 14 | // Where they were going comes back as `next`. | |
| 15 | assert.equal(workspaceGate("/acme/rocket", "?tab=pulls", nobody), `${NO_WORKSPACE_PATH}?next=${encodeURIComponent("/acme/rocket?tab=pulls")}`); | |
| 16 | }); | |
| 17 | ||
| 18 | test("the pages someone without a workspace needs stay open", () => { | |
| g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them. | 19 | for (const page of [NO_WORKSPACE_PATH, "/invitations", "/settings", "/settings/invites", "/logout", "/invite/g1t-k7m2", "/acme/rocket/invitations", "/notifications", "/inbox", "/u/ada", "/-/hovercard/user/ada"]) { |
| Merge workspace invitations: nobody joins a workspace without saying yes, people are found by username, your own invites can bring someone in, and nobody is left without a workspace (identity 0040) | 20 | assert.equal(workspaceGate(page, "", nobody), null, page); |
| 21 | } | |
| 22 | }); | |
| 23 | ||
| 24 | test("nobody else is gated: a member, an unconfirmed account, a repository collaborator, someone held by a policy, a visitor", () => { | |
| 25 | assert.equal(hasNoWorkspace(member), false); | |
| 26 | assert.equal(workspaceGate("/", "", member), null); | |
| 27 | assert.equal(workspaceGate("/", "", { ...nobody, verified: false }), null); | |
| 28 | assert.equal(workspaceGate("/", "", { ...nobody, grants: [{ repo: "acme/rocket" }] }), null); | |
| 29 | assert.equal(workspaceGate("/", "", { ...nobody, held: [{ slug: "acme" }] }), null); | |
| 30 | assert.equal(workspaceGate("/", "", { ...nobody, kind: "agent" }), null); | |
| 31 | assert.equal(workspaceGate("/", "", null), null); | |
| 32 | }); |
This file's history is long; its oldest lines are credited to the oldest commit read.