diff --git a/public/openapi.json b/public/openapi.json index 3bc7206..2faa843 100644 --- a/public/openapi.json +++ b/public/openapi.json @@ -7866,7 +7866,7 @@ "SignatureService" ], "summary": "ListPendingSignatures", - "description": "What the caller is asked to sign: their keyring when their keys changed, and the roster of\n each team they own when its members changed.", + "description": "What the caller is asked to sign: their keyring when their keys changed, the roster of each\n team they own when its members changed, and their settings when they or their projects did.", "operationId": "spin.v1.SignatureService.ListPendingSignatures", "parameters": [ { @@ -9903,7 +9903,7 @@ "WorkspaceService" ], "summary": "GetOwnerWord", - "description": "A workspace's newest access - who logs in, consent to collect logs, the settings approved -\n with what the next must say: the people the owner invited and the settings the guest would be\n handed now, for the owner to sign. Its owner's and its guests' to read.", + "description": "A workspace's newest access - who logs in - with what the next must say: the people the owner\n invited, for the owner to sign. Its owner's and its guests' to read.", "operationId": "spin.v1.WorkspaceService.GetOwnerWord", "parameters": [ { @@ -10522,7 +10522,7 @@ "WorkspaceService" ], "summary": "ListAgentThreads", - "description": "The agent's threads - T3 Code's chats - as the workspace's supervisor last reported them,\n which it does only while the owner's access consents (collect_logs). Titles, paths and\n times, never a message: the chat itself is read in T3 Code, over the owner's own session\n (`spin agent`).", + "description": "The agent's threads - T3 Code's chats - as the workspace's supervisor last reported them.\n Titles, paths and\n times, never a message: the chat itself is read in T3 Code, over the owner's own session\n (`spin agent`).", "operationId": "spin.v1.WorkspaceService.ListAgentThreads", "parameters": [ { @@ -13400,6 +13400,11 @@ "type": "string", "title": "workspace_id", "description": "The workspace the name was decided about, when allowed. The proxy pools connections by\n it and opens sessions for it: a name is freed by a rename and taken by someone else's\n workspace, and a connection pooled by name would carry the next request into the old one." + }, + "sessionRefused": { + "type": "boolean", + "title": "session_refused", + "description": "The session asked with is no good here: it has ended, or is another workspace's. The proxy\n drops the cookie, which would otherwise be sent and refused until it expires." } }, "title": "CheckPortAccessResponse", @@ -15886,52 +15891,6 @@ "title": "owner", "description": "owner is the workspace's owner, with their keyring as it is now: who signs the next. Empty\n keyring for an owner who has signed none." }, - "dotfiles": { - "allOf": [ - { - "$ref": "#/components/schemas/spin.v1.DotfilesConfig" - } - ], - "title": "dotfiles", - "description": "settings are the startup configuration the guest would be handed at its next registration:\n the owner's settings after the team's policy. A word approves them by their digest, which\n the client computes from these, as the guest does from what it is handed." - }, - "defaultShell": { - "type": "string", - "title": "default_shell" - }, - "env": { - "type": "object", - "title": "env", - "additionalProperties": { - "type": "string", - "title": "value" - } - }, - "editorSettings": { - "type": "object", - "title": "editor_settings", - "additionalProperties": { - "type": "string", - "title": "value" - } - }, - "taskfile": { - "type": "string", - "title": "taskfile" - }, - "egressRoot": { - "type": "string", - "title": "egress_root", - "description": "egress_root is the installation's egress root, PEM: what the guest is handed at registration,\n and trusts only when a word names its digest. A client names it only once it has held it to\n the root it pinned for the installation, never on this answer's say alone." - }, - "identityAudiences": { - "type": "array", - "items": { - "type": "string" - }, - "title": "identity_audiences", - "description": "identity_audiences is who the installation gives identities for, empty for anybody: what a\n client offers its owner to name in a word, which a host holds every token to as well." - }, "teamId": { "type": "string", "title": "team_id", @@ -15962,30 +15921,27 @@ "title": "role", "description": "role is the caller's: \"owner\", or \"guest\" - who reads it and signs nothing." }, - "repository": { + "ownerKeyring": { + "type": "array", + "items": { + "$ref": "#/components/schemas/spin.v1.SignedDocument" + }, + "title": "owner_keyring", + "description": "owner_keyring is, answered to the owner alone, their keyring's signed versions from the first:\n what their client holds the key an access is signed by to (roster.VerifyKeyrings), rather than\n the control plane's word of whose key it is." + }, + "standing": { "allOf": [ { - "$ref": "#/components/schemas/spin.v1.RepositoryConfig" + "$ref": "#/components/schemas/spin.v1.OwnerWord" } ], - "title": "repository", - "description": "repository is the one the workspace opened, part of the settings a word approves as the\n five above are: unset for a workspace that opened no project." + "title": "standing", + "description": "standing is the access a host lets people in by: the newest its owner signed with a key their\n newest keyring lists (ownerword.Newest). It is word, but where the key that signed word left\n the keyring: then it is what the next access is built on, which the client holds to\n owner_keyring before it does. Unset where no access a key of the keyring signed stands." }, - "prebuildClaim": { + "checkoutPath": { "type": "string", - "title": "prebuild_claim", - "format": "byte", - "description": "prebuild_claim is, for a workspace opened from a prebuild, the claim the host that built it\n signed (PrebuildClaim), whose SHA-256 repository.prebuild_claim_digest is: a client verifies\n it, and that it names the repository and the commit the settings do, before its word approves\n them." - }, - "prebuildWriters": { - "type": "object", - "title": "prebuild_writers", - "additionalProperties": { - "type": "string", - "title": "value", - "format": "byte" - }, - "description": "prebuild_writers is the record of the claim's writer, by its id (writers/\u003cid\u003e.json in the\n installation's store), which the client holds to its own anchors as it does a launch claim's." + "title": "checkout_path", + "description": "checkout_path is where the workspace's project is checked out (projects.CheckoutPath), empty\n for a workspace that opened none: where its agent works unless told otherwise." } }, "title": "GetOwnerWordResponse", @@ -17963,7 +17919,7 @@ } ], "title": "reported_at", - "description": "reported_at is when the supervisor last sent the index; unset where it never has - an owner\n who does not consent, or a workspace that ran no agent." + "description": "reported_at is when the supervisor last sent the index; unset where it never has - a\n workspace that ran no agent." } }, "title": "ListAgentThreadsResponse", @@ -19637,7 +19593,7 @@ }, "title": "OwnerWord", "additionalProperties": false, - "description": "OwnerWord is a workspace's access, as its owner signed it with a key of their keyring\n (internal/ownerword): document is the access as framed JSON, signature the key's SSH signature\n over it (sshsig, namespace \"spin-access\") - what `ssh-keygen -Y sign` writes, so a FIDO2 key\n signs one through ssh-agent." + "description": "OwnerWord is a workspace's access, as its owner signed it with a key of their keyring\n (internal/ownerword): document is the access as framed JSON, signature the key's over it for\n namespace \"spin-access\": an SSH signature (sshsig) - what `ssh-keygen -Y sign` writes, so a\n FIDO2 key signs one through ssh-agent - or a set's (sshsig.SignSet), one passkey prompt over\n several documents, which ssh-keygen does not read." }, "spin.v1.PageRequest": { "type": "object", @@ -19758,6 +19714,12 @@ "type": "boolean", "title": "deferred", "description": "deferred is a document nothing asks for until the person uses what it gives: the roster of a\n team that has only ever been its one member, read only for an identity. Offered there, not on\n every page." + }, + "previous": { + "type": "string", + "title": "previous", + "format": "byte", + "description": "previous is the version this one follows, as kept, for the client to show what changes\n against it; empty for none." } }, "title": "PendingSignature", @@ -20056,6 +20018,12 @@ } ], "title": "built_at" + }, + "workspaceCount": { + "type": "integer", + "title": "workspace_count", + "format": "int32", + "description": "In ListPrebuilds: the workspaces opened from it that are not deleted, whoever's they are." } }, "title": "Prebuild", @@ -20211,6 +20179,12 @@ "type": "string" }, "title": "shared_team_ids" + }, + "readyPrebuildCount": { + "type": "integer", + "title": "ready_prebuild_count", + "format": "int32", + "description": "In ListProjects: how many of its prebuilds are ready to open from." } }, "title": "Project", @@ -20678,59 +20652,6 @@ "title": "RemoveWorkspaceGuestResponse", "additionalProperties": false }, - "spin.v1.RepositoryConfig": { - "type": "object", - "properties": { - "url": { - "type": "string", - "title": "url" - }, - "ref": { - "type": "string", - "title": "ref" - }, - "path": { - "type": "string", - "title": "path" - }, - "authorName": { - "type": "string", - "title": "author_name", - "description": "Who the checkout's commits are by: the workspace's owner's name and email as the installation\n knows them, set as the checkout's own user.name and user.email - the push goes as the team's\n app, and the commit says the person. Empty is neither set." - }, - "authorEmail": { - "type": "string", - "title": "author_email" - }, - "commit": { - "type": "string", - "title": "commit", - "description": "commit is the one a prebuild's build checks out and runs create at; empty for a workspace a\n person opens, which follows the ref." - }, - "fromCommit": { - "type": "string", - "title": "from_commit", - "description": "from_commit is the commit the disk's checkout already is, for a disk cloned from a prebuild:\n the guest holds the tree to it (git fsck, no tracked file changed) before it fetches." - }, - "prebuildId": { - "type": "string", - "title": "prebuild_id", - "description": "The prebuild the disk is a clone of, and the SHA-256 of the claim its host signed of it\n (PrebuildClaim): what the owner approves when the open was from one." - }, - "prebuildClaimDigest": { - "type": "string", - "title": "prebuild_claim_digest" - }, - "pullRef": { - "type": "string", - "title": "pull_ref", - "description": "pull_ref is a pull request's ref as its forge serves it (refs/pull/\u003cn\u003e/head, GitLab's\n refs/merge-requests/\u003cn\u003e/head), fetched once ref is cloned and checked out as pr-\u003cn\u003e or mr-\u003cn\u003e;\n empty for a workspace that opens at ref itself." - } - }, - "title": "RepositoryConfig", - "additionalProperties": false, - "description": "The repository a workspace opened, as its guest clones it: the project's URL, the ref the\n workspace was opened at, and where on the disk it goes (projects.CheckoutPath). Part of the\n settings the owner approves, as the environment is: a disk is written to only as its owner said." - }, "spin.v1.RequestHostShellRequest": { "type": "object", "properties": { @@ -20899,6 +20820,12 @@ "type": "string", "title": "host_class", "description": "The host class its workspaces run on (HostClass)." + }, + "agentMinMemoryMb": { + "type": "integer", + "title": "agent_min_memory_mb", + "format": "int32", + "description": "What a workspace has to hold for its agent to start there, in MB, for whoever picks a preset." } }, "title": "ResourcePreset", @@ -22091,13 +22018,15 @@ "enum": [ "SIGNATURE_KIND_UNSPECIFIED", "SIGNATURE_KIND_KEYRING", - "SIGNATURE_KIND_ROSTER" + "SIGNATURE_KIND_ROSTER", + "SIGNATURE_KIND_SETTINGS" ], - "description": "- `SIGNATURE_KIND_KEYRING`: A user's keyring: the keys that may sign for them (roster.Keyring). Signed with a key of the\n keyring before it; the first, and one started anew, with a key it lists.\n- `SIGNATURE_KIND_ROSTER`: A team's roster: its members, its owners and each member's keyring (roster.Roster). Signed by\n an owner the roster before it lists; the first, by an owner it lists.", + "description": "- `SIGNATURE_KIND_KEYRING`: A user's keyring: the keys that may sign for them (roster.Keyring). Signed with a key of the\n keyring before it; the first, and one started anew, with a key it lists.\n- `SIGNATURE_KIND_ROSTER`: A team's roster: its members, its owners and each member's keyring (roster.Roster). Signed by\n an owner the roster before it lists; the first, by an owner it lists.\n- `SIGNATURE_KIND_SETTINGS`: A user's settings: what their workspaces apply - dotfiles, shell, environment, editor,\n Taskfile, each workspace's own environment - and the repositories, by URL and ref, their\n workspaces may clone (ownersettings.Settings). Signed with a key of their newest keyring, never\n a session's: a host applies nothing else of theirs.", "x-enum-descriptions": [ "", "A user's keyring: the keys that may sign for them (roster.Keyring). Signed with a key of the\n keyring before it; the first, and one started anew, with a key it lists.", - "A team's roster: its members, its owners and each member's keyring (roster.Roster). Signed by\n an owner the roster before it lists; the first, by an owner it lists." + "A team's roster: its members, its owners and each member's keyring (roster.Roster). Signed by\n an owner the roster before it lists; the first, by an owner it lists.", + "A user's settings: what their workspaces apply - dotfiles, shell, environment, editor,\n Taskfile, each workspace's own environment - and the repositories, by URL and ref, their\n workspaces may clone (ownersettings.Settings). Signed with a key of their newest keyring, never\n a session's: a host applies nothing else of theirs." ] }, "spin.v1.SignedDocument": { @@ -22116,7 +22045,7 @@ }, "title": "SignedDocument", "additionalProperties": false, - "description": "SignedDocument is a document as framed JSON and an SSH signature over it (sshsig) - what\n `ssh-keygen -Y sign` writes, so a FIDO2 key signs one through ssh-agent, and a passkey's\n WebAuthn assertion is one too (internal/sshauth)." + "description": "SignedDocument is a document as framed JSON and a signature over it: an SSH signature (sshsig) -\n what `ssh-keygen -Y sign` writes, so a FIDO2 key signs one through ssh-agent, and a passkey's\n WebAuthn assertion is one too (internal/sshauth) - or a set's (sshsig.SignSet), one passkey\n prompt over several documents, which ssh-keygen does not read." }, "spin.v1.Snapshot": { "type": "object", @@ -24476,6 +24405,22 @@ "type": "string", "title": "suspended_snapshot_id", "description": "The snapshot it was suspended into: its next start resumes it rather than booting its disk.\n Empty when a start boots the disk - never suspended, resumed since, or the snapshot deleted." + }, + "fromPrebuildId": { + "type": "string", + "title": "from_prebuild_id", + "description": "The prebuild its disk is a clone of; empty for one that opened with none." + }, + "agentMinMemoryMb": { + "type": "integer", + "title": "agent_min_memory_mb", + "format": "int32", + "description": "What it has to hold for its agent to start there, in MB (the supervisor refuses below it)." + }, + "projectError": { + "type": "string", + "title": "project_error", + "description": "project_error is what its guest last said went wrong with its project - the clone, its\n .spin.yaml or its create tasks - as the guest said it; empty when all of it went, or nothing\n has reported. The next boot tries again." } }, "title": "Workspace", @@ -25223,6 +25168,10 @@ "name": "SetupService", "description": "SetupService handles initial platform setup and admin bootstrap.\n Most endpoints require admin authentication, except GetSetupStatus and PasswordLogin." }, + { + "name": "SignatureService", + "description": "SignatureService is what only people sign of themselves: who a user's keys are, who a team's\n members are, and which settings their workspaces apply. A host holds every workspace's access\n and settings to these (internal/roster), so the control plane can say neither which keys are\n somebody's, nor who is in a team, nor what a guest applies for its owner. A workspace's access is\n signed through WorkspaceService.SetOwnerWord.\n\n The control plane proposes each document from what it holds - a key registered, a member added -\n and keeps what was signed; it signs nothing. A client shows a person what they are signing and\n signs it with a key of theirs: `spin sign`, with the keys ssh-agent holds, or the terminal's\n page, with a passkey." + }, { "name": "WorkspaceService" }, @@ -25230,10 +25179,6 @@ "name": "ShareService", "description": "ShareService manages snapshot sharing\n Snapshots can be shared with specific users or made public\n Users can create new workspaces from shared snapshots" }, - { - "name": "SignatureService", - "description": "SignatureService is what only people sign of themselves: who a user's keys are and who a team's\n members are. A host holds every workspace's access to these (internal/roster), so a control\n plane that is taken can say neither which keys are somebody's nor who is in a team. A\n workspace's access is signed through WorkspaceService.SetOwnerWord.\n\n The control plane proposes each document from what it holds - a key registered, a member added -\n and keeps what was signed; it signs nothing. A client shows a person what they are signing and\n signs it with a key of theirs: `spin sign`, with the keys ssh-agent holds, or the terminal's\n page, with a passkey." - }, { "name": "SSHKeyService", "description": "SSHKeyService is the user's own keys, as a registry: the ones a client offers when the owner\n signs a workspace's word (OwnerWord), and the anchor a create may name. A key here logs in to\n nothing on its own - only a key the owner's word for a workspace lists does, there." diff --git a/src/assets/diagrams/egress-policy.svg b/src/assets/diagrams/egress-policy.svg index 00e1e19..dafce86 100644 --- a/src/assets/diagrams/egress-policy.svg +++ b/src/assets/diagrams/egress-policy.svg @@ -4,193 +4,260 @@ - - + + egress_policy - -What the forward chain decides, in order + +What the forward chain decides, in order in - -a packet from a machine -iifname veth-eg-* + +a packet from a machine +iifname veth-eg-* node1 - -1 · ip daddr in the node's own space -    10/8 · 172.16/12 · 192.168/16 · 127/8 -    169.254/16 · 100.64/10 · 224/4 · 240/4 -    + every address the node answers on + +1 · ip daddr in the node's own space +    10/8 · 172.16/12 · 192.168/16 · 127/8 +    169.254/16 · 100.64/10 · 224/4 · 240/4 +    + every address the node answers on in->node1 - - + + - + -tagA - -2 · ip saddr @tag_<name>  ip daddr <allowed> -    what a tag permits +agent + +1a · ip dscp <agent's mark> +    an agent's packet: only the egress proxy +    stands in for what it may reach - + -node1->tagA - - -  no +node1->agent + + +  no - + dropped - -dropped, and counted + +dropped, and counted node1->dropped - - -  match + + +  match - + -tagD - -3 · ip saddr @tag_<name> -    and nothing else, when the tag says so +open + +1b · oifname wan0  ct state established,related +    what the machine already had open - + -tagA->tagD - - -  no +agent->open + + +  no + + + +agent->dropped + + +  match + + + +held + +1c · ip saddr @held +    a machine taken back from the last runner, +    until its record says what it carries + + + +open->held + + +  no - + allowed - -accepted - and recorded in @observed -machine . destination, with a counter, 6 h + +accepted - and recorded in @observed +machine . destination, with a counter, 6 h + + + +open->allowed + + +  match + + + +tagA + +2 · ip saddr @tag_<name>  ip daddr <allowed> +    what a tag permits + + + +held->tagA + + +  no + + + +held->dropped + + +  match + + + +tagD + +3 · ip saddr @tag_<name> +    and nothing else, when the tag says so + + + +tagA->tagD + + +  no - + tagA->allowed - - -  match + + +  match - + dflt - -4 · oifname wan0 -    the default: open beyond the node + +4 · oifname wan0 +    the default: open beyond the node - + tagD->dflt - - -  no + + +  no - + tagD->dropped - - -  match + + +  match - + home - -5 · iifname wan0  ct state established,related -    the way back, and only for a connection -    a machine opened + +5 · iifname wan0  ct state established,related +    the way back, and only for a connection +    a machine opened - + dflt->home - - -  no + + +  no - + dflt->allowed - - -  match + + +  match - + lat - -6 · veth-eg-* to veth-eg-* -    one machine to another, said out loud + +6 · veth-eg-* to veth-eg-* +    one machine to another, said out loud - + home->lat - - -  no + + +  no - + home->allowed - - -  match + + +  match - + lat->dropped - - -  match + + +  match - + policy - -no rule claimed it -policy drop + +no rule claimed it +policy drop - + lat->policy - - -  no + + +  no - + note - - - -Why this order. -1 is first because 4 is what would otherwise carry it: the -node's LAN is reached through the uplink like everything else, -so a drop written after the accept never runs. It matches the -destination alone and not the pair of interfaces - what is kept -away is a place, not a path, and a rule naming wan0 would stop -applying the day there is a second way out. -2 and 3 are between them, so a tag cannot open the node and a -tag that closes a machine is reached by what its own rules did -not claim. -4 is open on purpose. There is no allowlist to write yet, so -the accept records where it went instead - see @observed, and -`SIGUSR1` to the runner. + + + +Why this order. +1 is first because 4 is what would otherwise carry it: the +node's LAN is reached through the uplink like everything else, +so a drop written after the accept never runs. It matches the +destination alone and not the pair of interfaces - what is kept +away is a place, not a path, and a rule naming wan0 would stop +applying the day there is a second way out. +2 and 3 are between them, so a tag cannot open the node and a +tag that closes a machine is reached by what its own rules did +not claim. +1c is after 1b, so a runner's restart cuts nothing a machine +had open, and before 4, which a machine in no tag set reaches. +4 is open on purpose. There is no allowlist to write yet, so +the accept records where it went instead - see @observed, and +`SIGUSR1` to the runner. diff --git a/src/assets/shots/snapshots.png b/src/assets/shots/snapshots.png index e8f8846..94676e6 100644 Binary files a/src/assets/shots/snapshots.png and b/src/assets/shots/snapshots.png differ diff --git a/src/assets/shots/workspace.png b/src/assets/shots/workspace.png index f074a29..2ebec62 100644 Binary files a/src/assets/shots/workspace.png and b/src/assets/shots/workspace.png differ diff --git a/src/assets/shots/workspaces.png b/src/assets/shots/workspaces.png index 4132580..941ad38 100644 Binary files a/src/assets/shots/workspaces.png and b/src/assets/shots/workspaces.png differ diff --git a/src/content/docs/reference/api/index.md b/src/content/docs/reference/api/index.md index 4a96f4d..afc32e2 100644 --- a/src/content/docs/reference/api/index.md +++ b/src/content/docs/reference/api/index.md @@ -30,9 +30,9 @@ curl -s https://app.example.com/spin.v1.WorkspaceService/ListWorkspaces \ - [RunnerTokenService](/reference/api/runnertokenservice/): 4 procedures - [SettingsService](/reference/api/settingsservice/): 3 procedures - [SetupService](/reference/api/setupservice/): SetupService handles initial platform setup and admin bootstrap. Most endpoints require admin authentication, except GetSetupStatus and PasswordLogin. +- [SignatureService](/reference/api/signatureservice/): SignatureService is what only people sign of themselves: who a user's keys are, who a team's. members are, and which settings their workspaces apply. A host holds every workspace's access. and settings to these (internal/roster), so the control plane can say neither which keys are. somebody's, nor who is in a team, nor what a guest applies for its owner. A workspace's access is. signed through WorkspaceService.SetOwnerWord. The control plane proposes each document from what it holds - a key registered, a member added -. and keeps what was signed; it signs nothing. A client shows a person what they are signing and. signs it with a key of theirs: `spin sign`, with the keys ssh-agent holds, or the terminal's. page, with a passkey. - [WorkspaceService](/reference/api/workspaceservice/): 53 procedures - [ShareService](/reference/api/shareservice/): ShareService manages snapshot sharing. Snapshots can be shared with specific users or made public. Users can create new workspaces from shared snapshots. -- [SignatureService](/reference/api/signatureservice/): SignatureService is what only people sign of themselves: who a user's keys are and who a team's. members are. A host holds every workspace's access to these (internal/roster), so a control. plane that is taken can say neither which keys are somebody's nor who is in a team. A. workspace's access is signed through WorkspaceService.SetOwnerWord. The control plane proposes each document from what it holds - a key registered, a member added -. and keeps what was signed; it signs nothing. A client shows a person what they are signing and. signs it with a key of theirs: `spin sign`, with the keys ssh-agent holds, or the terminal's. page, with a passkey. - [SSHKeyService](/reference/api/sshkeyservice/): SSHKeyService is the user's own keys, as a registry: the ones a client offers when the owner. signs a workspace's word (OwnerWord), and the anchor a create may name. A key here logs in to. nothing on its own - only a key the owner's word for a workspace lists does, there. - [TeamService](/reference/api/teamservice/): 18 procedures - [Types](/reference/api/types/): every message and enum the procedures name diff --git a/src/content/docs/reference/api/shareservice.md b/src/content/docs/reference/api/shareservice.md index 3a39005..f56b312 100644 --- a/src/content/docs/reference/api/shareservice.md +++ b/src/content/docs/reference/api/shareservice.md @@ -4,7 +4,7 @@ description: "spin.v1.ShareService: each procedure, its request and its response source: "spin:internal/controlplane/apidocs/spin.v1.openapi.json" editUrl: false sidebar: - order: 12 + order: 13 --- diff --git a/src/content/docs/reference/api/signatureservice.md b/src/content/docs/reference/api/signatureservice.md index 01a787c..007e049 100644 --- a/src/content/docs/reference/api/signatureservice.md +++ b/src/content/docs/reference/api/signatureservice.md @@ -4,18 +4,18 @@ description: "spin.v1.SignatureService: each procedure, its request and its resp source: "spin:internal/controlplane/apidocs/spin.v1.openapi.json" editUrl: false sidebar: - order: 13 + order: 11 --- -SignatureService is what only people sign of themselves: who a user's keys are and who a team's. members are. A host holds every workspace's access to these (internal/roster), so a control. plane that is taken can say neither which keys are somebody's nor who is in a team. A. workspace's access is signed through WorkspaceService.SetOwnerWord. The control plane proposes each document from what it holds - a key registered, a member added -. and keeps what was signed; it signs nothing. A client shows a person what they are signing and. signs it with a key of theirs: `spin sign`, with the keys ssh-agent holds, or the terminal's. page, with a passkey. +SignatureService is what only people sign of themselves: who a user's keys are, who a team's. members are, and which settings their workspaces apply. A host holds every workspace's access. and settings to these (internal/roster), so the control plane can say neither which keys are. somebody's, nor who is in a team, nor what a guest applies for its owner. A workspace's access is. signed through WorkspaceService.SetOwnerWord. The control plane proposes each document from what it holds - a key registered, a member added -. and keeps what was signed; it signs nothing. A client shows a person what they are signing and. signs it with a key of theirs: `spin sign`, with the keys ssh-agent holds, or the terminal's. page, with a passkey. ## ListPendingSignatures `POST /spin.v1.SignatureService/ListPendingSignatures` -What the caller is asked to sign: their keyring when their keys changed, and the roster of each team they own when its members changed. +What the caller is asked to sign: their keyring when their keys changed, the roster of each team they own when its members changed, and their settings when they or their projects did. **Request** diff --git a/src/content/docs/reference/api/types.md b/src/content/docs/reference/api/types.md index 9be7d42..78e3222 100644 --- a/src/content/docs/reference/api/types.md +++ b/src/content/docs/reference/api/types.md @@ -701,7 +701,7 @@ One of: `OUTSIDE_SHARE_STATE_UNSPECIFIED`, `OUTSIDE_SHARE_STATE_PREPARING`, `OUT ## OwnerWord -OwnerWord is a workspace's access, as its owner signed it with a key of their keyring (internal/ownerword): document is the access as framed JSON, signature the key's SSH signature over it (sshsig, namespace "spin-access") - what `ssh-keygen -Y sign` writes, so a FIDO2 key signs one through ssh-agent. +OwnerWord is a workspace's access, as its owner signed it with a key of their keyring (internal/ownerword): document is the access as framed JSON, signature the key's over it for namespace "spin-access": an SSH signature (sshsig) - what `ssh-keygen -Y sign` writes, so a FIDO2 key signs one through ssh-agent - or a set's (sshsig.SignSet), one passkey prompt over several documents, which ssh-keygen does not read. | Field | Type | What it is | |---|---|---| @@ -736,6 +736,7 @@ PendingSignature is one document the caller is asked to sign. | `signers` | list of string | signers are the keys, in authorized_keys form, any one of which may sign it. | | `summary` | string | summary is a line saying what it changes, for a list: the document itself is what to read. | | `deferred` | boolean | deferred is a document nothing asks for until the person uses what it gives: the roster of a team that has only ever been its one member, read only for an identity. Offered there, not on every page. | +| `previous` | string (byte) | previous is the version this one follows, as kept, for the client to show what changes against it; empty for none. | ## PlatformImage @@ -796,6 +797,7 @@ A prebuild: one build of a project's ref at a commit, and the snapshot it left. | `error` | string | | | `createdAt` | `Timestamp` | | | `builtAt` | `Timestamp` | | +| `workspaceCount` | integer (int32) | In ListPrebuilds: the workspaces opened from it that are not deleted, whoever's they are. | ## PrebuildState @@ -835,6 +837,7 @@ A project: a repository and the shape of the workspace that opens it. | `adminIds` | list of string | Its admins and whom it is shared with: shown to its admins, empty to everybody else. | | `sharedUserIds` | list of string | | | `sharedTeamIds` | list of string | | +| `readyPrebuildCount` | integer (int32) | In ListProjects: how many of its prebuilds are ready to open from. | ## QuarantineDenial @@ -894,23 +897,6 @@ RekeyState is how far a disk's re-key is. - `REKEY_STATE_PENDING`: Marked by a r One of: `REKEY_STATE_UNSPECIFIED`, `REKEY_STATE_PENDING`, `REKEY_STATE_COPYING`, `REKEY_STATE_READY`. -## RepositoryConfig - -The repository a workspace opened, as its guest clones it: the project's URL, the ref the workspace was opened at, and where on the disk it goes (projects.CheckoutPath). Part of the settings the owner approves, as the environment is: a disk is written to only as its owner said. - -| Field | Type | What it is | -|---|---|---| -| `url` | string | | -| `ref` | string | | -| `path` | string | | -| `authorName` | string | Who the checkout's commits are by: the workspace's owner's name and email as the installation knows them, set as the checkout's own user.name and user.email - the push goes as the team's app, and the commit says the person. Empty is neither set. | -| `authorEmail` | string | | -| `commit` | string | commit is the one a prebuild's build checks out and runs create at; empty for a workspace a person opens, which follows the ref. | -| `fromCommit` | string | from_commit is the commit the disk's checkout already is, for a disk cloned from a prebuild: the guest holds the tree to it (git fsck, no tracked file changed) before it fetches. | -| `prebuildId` | string | The prebuild the disk is a clone of, and the SHA-256 of the claim its host signed of it (PrebuildClaim): what the owner approves when the open was from one. | -| `prebuildClaimDigest` | string | | -| `pullRef` | string | pull_ref is a pull request's ref as its forge serves it (refs/pull/<n>/head, GitLab's refs/merge-requests/<n>/head), fetched once ref is cloned and checked out as pr-<n> or mr-<n>; empty for a workspace that opens at ref itself. | - ## ResolverLookup | Field | Type | What it is | @@ -942,6 +928,7 @@ ResourcePreset is a class of workspace: its size, and how a workspace of it may | `bandwidthMbps` | integer (int32) | What a workspace of it may carry each way, in megabits a second; 0 is unshaped. | | `rpoSeconds` | integer (int32) | How far behind the object store a workspace of it may fall, in seconds; 0 is the installation's (InstallationSettings.volume_rpo_seconds). | | `hostClass` | string | The host class its workspaces run on (HostClass). | +| `agentMinMemoryMb` | integer (int32) | What a workspace has to hold for its agent to start there, in MB, for whoever picks a preset. | ## Resources @@ -1013,13 +1000,13 @@ ServiceHealth is one service over a window: the traces begun in it - what it was ## SignatureKind -- `SIGNATURE_KIND_KEYRING`: A user's keyring: the keys that may sign for them (roster.Keyring). Signed with a key of the keyring before it; the first, and one started anew, with a key it lists. - `SIGNATURE_KIND_ROSTER`: A team's roster: its members, its owners and each member's keyring (roster.Roster). Signed by an owner the roster before it lists; the first, by an owner it lists. +- `SIGNATURE_KIND_KEYRING`: A user's keyring: the keys that may sign for them (roster.Keyring). Signed with a key of the keyring before it; the first, and one started anew, with a key it lists. - `SIGNATURE_KIND_ROSTER`: A team's roster: its members, its owners and each member's keyring (roster.Roster). Signed by an owner the roster before it lists; the first, by an owner it lists. - `SIGNATURE_KIND_SETTINGS`: A user's settings: what their workspaces apply - dotfiles, shell, environment, editor, Taskfile, each workspace's own environment - and the repositories, by URL and ref, their workspaces may clone (ownersettings.Settings). Signed with a key of their newest keyring, never a session's: a host applies nothing else of theirs. -One of: `SIGNATURE_KIND_UNSPECIFIED`, `SIGNATURE_KIND_KEYRING`, `SIGNATURE_KIND_ROSTER`. +One of: `SIGNATURE_KIND_UNSPECIFIED`, `SIGNATURE_KIND_KEYRING`, `SIGNATURE_KIND_ROSTER`, `SIGNATURE_KIND_SETTINGS`. ## SignedDocument -SignedDocument is a document as framed JSON and an SSH signature over it (sshsig) - what `ssh-keygen -Y sign` writes, so a FIDO2 key signs one through ssh-agent, and a passkey's WebAuthn assertion is one too (internal/sshauth). +SignedDocument is a document as framed JSON and a signature over it: an SSH signature (sshsig) - what `ssh-keygen -Y sign` writes, so a FIDO2 key signs one through ssh-agent, and a passkey's WebAuthn assertion is one too (internal/sshauth) - or a set's (sshsig.SignSet), one passkey prompt over several documents, which ssh-keygen does not read. | Field | Type | What it is | |---|---|---| @@ -1328,6 +1315,9 @@ VolumeRekey is a workspace's disk to re-key or being re-keyed. | `ref` | string | | | `wakeOnAccess` | boolean | Suspended, it is resumed by a signed-in visitor of one of its published ports (OpenWorkspaceProxySession). Never by an anonymous one: that would undo the idle suspension for whoever has a public port's URL. | | `suspendedSnapshotId` | string | The snapshot it was suspended into: its next start resumes it rather than booting its disk. Empty when a start boots the disk - never suspended, resumed since, or the snapshot deleted. | +| `fromPrebuildId` | string | The prebuild its disk is a clone of; empty for one that opened with none. | +| `agentMinMemoryMb` | integer (int32) | What it has to hold for its agent to start there, in MB (the supervisor refuses below it). | +| `projectError` | string | project_error is what its guest last said went wrong with its project - the clone, its .spin.yaml or its create tasks - as the guest said it; empty when all of it went, or nothing has reported. The next boot tries again. | ## WorkspaceAction diff --git a/src/content/docs/reference/api/workspaceservice.md b/src/content/docs/reference/api/workspaceservice.md index b2da469..5d425c0 100644 --- a/src/content/docs/reference/api/workspaceservice.md +++ b/src/content/docs/reference/api/workspaceservice.md @@ -4,7 +4,7 @@ description: "spin.v1.WorkspaceService: each procedure, its request and its resp source: "spin:internal/controlplane/apidocs/spin.v1.openapi.json" editUrl: false sidebar: - order: 11 + order: 12 --- @@ -71,6 +71,7 @@ Whether one request may reach one published port. The gate in front of them. | `allowed` | boolean | | | `access` | [PortAccess](/reference/api/types/#portaccess) | What the port's level is, so the proxy can tell a refusal that a login would fix from one it would not: an anonymous request to a PRIVATE port is a redirect, and a signed-in request to the same port is a 403 no amount of signing in changes. | | `workspaceId` | string | The workspace the name was decided about, when allowed. The proxy pools connections by it and opens sessions for it: a name is freed by a rename and taken by someone else's workspace, and a connection pooled by name would carry the next request into the old one. | +| `sessionRefused` | boolean | The session asked with is no good here: it has ended, or is another workspace's. The proxy drops the cookie, which would otherwise be sent and refused until it expires. | ## CheckPortPublished @@ -261,7 +262,7 @@ Port exposure `POST /spin.v1.WorkspaceService/GetOwnerWord` -A workspace's newest access - who logs in, consent to collect logs, the settings approved - with what the next must say: the people the owner invited and the settings the guest would be handed now, for the owner to sign. Its owner's and its guests' to read. +A workspace's newest access - who logs in - with what the next must say: the people the owner invited, for the owner to sign. Its owner's and its guests' to read. **Request** @@ -275,22 +276,15 @@ A workspace's newest access - who logs in, consent to collect logs, the settings |---|---|---| | `word` | [OwnerWord](/reference/api/types/#ownerword) | word is the newest the owner signed; unset for a workspace whose owner has signed none. | | `owner` | [AccessPerson](/reference/api/types/#accessperson) | owner is the workspace's owner, with their keyring as it is now: who signs the next. Empty keyring for an owner who has signed none. | -| `dotfiles` | [DotfilesConfig](/reference/api/types/#dotfilesconfig) | settings are the startup configuration the guest would be handed at its next registration: the owner's settings after the team's policy. A word approves them by their digest, which the client computes from these, as the guest does from what it is handed. | -| `defaultShell` | string | | -| `env` | map of string to string | | -| `editorSettings` | map of string to string | | -| `taskfile` | string | | -| `egressRoot` | string | egress_root is the installation's egress root, PEM: what the guest is handed at registration, and trusts only when a word names its digest. A client names it only once it has held it to the root it pinned for the installation, never on this answer's say alone. | -| `identityAudiences` | list of string | identity_audiences is who the installation gives identities for, empty for anybody: what a client offers its owner to name in a word, which a host holds every token to as well. | | `teamId` | string | The workspace as its first access says it: team, image, and the snapshot and workspace it was cloned from. The next access says the same; the first says these. | | `image` | string | | | `parentSnapshotId` | string | | | `parentWorkspaceId` | string | | | `guests` | list of [AccessPerson](/reference/api/types/#accessperson) | guests are the people the owner invited, each with their keyring as it is now: who the next access names besides the owner. One with an empty keyring has signed none, and is named once they have. | | `role` | string | role is the caller's: "owner", or "guest" - who reads it and signs nothing. | -| `repository` | [RepositoryConfig](/reference/api/types/#repositoryconfig) | repository is the one the workspace opened, part of the settings a word approves as the five above are: unset for a workspace that opened no project. | -| `prebuildClaim` | string (byte) | prebuild_claim is, for a workspace opened from a prebuild, the claim the host that built it signed (PrebuildClaim), whose SHA-256 repository.prebuild_claim_digest is: a client verifies it, and that it names the repository and the commit the settings do, before its word approves them. | -| `prebuildWriters` | map of string to string (byte) | prebuild_writers is the record of the claim's writer, by its id (writers/<id>.json in the installation's store), which the client holds to its own anchors as it does a launch claim's. | +| `ownerKeyring` | list of [SignedDocument](/reference/api/types/#signeddocument) | owner_keyring is, answered to the owner alone, their keyring's signed versions from the first: what their client holds the key an access is signed by to (roster.VerifyKeyrings), rather than the control plane's word of whose key it is. | +| `standing` | [OwnerWord](/reference/api/types/#ownerword) | standing is the access a host lets people in by: the newest its owner signed with a key their newest keyring lists (ownerword.Newest). It is word, but where the key that signed word left the keyring: then it is what the next access is built on, which the client holds to owner_keyring before it does. Unset where no access a key of the keyring signed stands. | +| `checkoutPath` | string | checkout_path is where the workspace's project is checked out (projects.CheckoutPath), empty for a workspace that opened none: where its agent works unless told otherwise. | ## GetWorkspace @@ -483,7 +477,7 @@ Keep a running workspace awake for a while: neither the idle suspension nor the `POST /spin.v1.WorkspaceService/ListAgentThreads` -The agent's threads - T3 Code's chats - as the workspace's supervisor last reported them, which it does only while the owner's access consents (collect_logs). Titles, paths and times, never a message: the chat itself is read in T3 Code, over the owner's own session (`spin agent`). +The agent's threads - T3 Code's chats - as the workspace's supervisor last reported them. Titles, paths and times, never a message: the chat itself is read in T3 Code, over the owner's own session (`spin agent`). **Request** @@ -497,7 +491,7 @@ The agent's threads - T3 Code's chats - as the workspace's supervisor last repor |---|---|---| | `environmentId` | string | environment_id is T3 Code's id for the workspace's server: a thread's page in its web client is /<environment_id>/<thread id>, served at the port `spin agent` forwards. | | `threads` | list of [AgentThread](/reference/api/types/#agentthread) | Newest first. | -| `reportedAt` | `Timestamp` | reported_at is when the supervisor last sent the index; unset where it never has - an owner who does not consent, or a workspace that ran no agent. | +| `reportedAt` | `Timestamp` | reported_at is when the supervisor last sent the index; unset where it never has - a workspace that ran no agent. | ## ListAgentVolumes diff --git a/src/content/docs/reference/cli/admin.md b/src/content/docs/reference/cli/admin.md index 926e691..44b709b 100644 --- a/src/content/docs/reference/cli/admin.md +++ b/src/content/docs/reference/cli/admin.md @@ -33,9 +33,10 @@ Flags: -h, --help help for admin Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false Use "spin admin [command] --help" for more information about a command. ``` @@ -59,9 +60,10 @@ Flags: --month string the month, as 2026-10 (default: this month) Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false Use "spin admin costs [command] --help" for more information about a command. ``` @@ -82,9 +84,10 @@ Flags: --month string the month, as 2026-10 (default: this month) Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin admin jobs @@ -104,9 +107,10 @@ Flags: -h, --help help for jobs Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false Use "spin admin jobs [command] --help" for more information about a command. ``` @@ -123,9 +127,10 @@ Flags: -h, --help help for list Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` #### spin admin jobs run @@ -141,9 +146,10 @@ Flags: -h, --help help for run Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin admin logs @@ -167,9 +173,10 @@ Flags: --since duration how far back to look, at most 744h (31 days) (default 1h0m0s) Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin admin runner @@ -192,9 +199,10 @@ Flags: -h, --help help for runner Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false Use "spin admin runner [command] --help" for more information about a command. ``` @@ -213,9 +221,10 @@ Flags: -h, --help help for activate Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` #### spin admin runner drain @@ -240,9 +249,10 @@ Flags: --suspend Suspend the runner's running workspaces so they resume elsewhere Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` #### spin admin runner list @@ -257,9 +267,10 @@ Flags: -h, --help help for list Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` #### spin admin runner policy @@ -296,9 +307,10 @@ Flags: --writeback-limit-bytes int dirty page cache this runner holds before a writer waits (vm.dirty_bytes); unset is what it booted with Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` #### spin admin runner revoke @@ -324,9 +336,10 @@ Flags: -y, --yes Skip confirmation Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin admin shell @@ -357,9 +370,10 @@ Flags: -h, --help help for shell Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false Use "spin admin shell [command] --help" for more information about a command. ``` @@ -376,9 +390,10 @@ Flags: -h, --help help for approve Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` #### spin admin shell close @@ -393,9 +408,10 @@ Flags: -h, --help help for close Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` #### spin admin shell list @@ -410,9 +426,10 @@ Flags: -h, --help help for list Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` #### spin admin shell open @@ -437,9 +454,10 @@ Flags: --reason string Why: said to whoever approves it, and kept Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` #### spin admin shell recording @@ -456,9 +474,10 @@ Flags: -h, --help help for recording Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin admin storage @@ -479,9 +498,10 @@ Flags: -h, --help help for storage Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false Use "spin admin storage [command] --help" for more information about a command. ``` @@ -499,9 +519,10 @@ Flags: -h, --help help for list Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` #### spin admin storage remove @@ -521,9 +542,10 @@ Flags: -y, --yes Skip confirmation Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` #### spin admin storage untag-image @@ -540,9 +562,10 @@ Flags: -h, --help help for untag-image Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin admin token @@ -563,9 +586,10 @@ Flags: -h, --help help for token Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false Use "spin admin token [command] --help" for more information about a command. ``` @@ -616,9 +640,10 @@ Flags: --writeback-limit-bytes int dirty page cache each host it registers holds before a writer waits (vm.dirty_bytes); unset is what it booted with Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` #### spin admin token list @@ -634,9 +659,10 @@ Flags: --include-used Include already-used tokens Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` #### spin admin token revoke @@ -651,9 +677,10 @@ Flags: -h, --help help for revoke Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin admin versions @@ -668,9 +695,10 @@ Flags: -h, --help help for versions Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin admin volume @@ -690,9 +718,10 @@ Flags: -h, --help help for volume Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false Use "spin admin volume [command] --help" for more information about a command. ``` @@ -714,9 +743,10 @@ Flags: -y, --yes Skip confirmation Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` #### spin admin volume rekeys @@ -731,8 +761,9 @@ Flags: -h, --help help for rekeys Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` diff --git a/src/content/docs/reference/cli/agent.md b/src/content/docs/reference/cli/agent.md index d5e0e72..a335bb0 100644 --- a/src/content/docs/reference/cli/agent.md +++ b/src/content/docs/reference/cli/agent.md @@ -22,8 +22,8 @@ forwarding; the server goes on for half an hour with nothing asked of it and no then stops, and its threads stay in the agent's home on the disk. path defaults to the project's checkout; a workspace with no project is told where to work. -T3 Code's server is a Node program that wants a workspace of two gigabytes or more: in one of -a gigabyte the kernel kills it as it starts. +T3 Code's server is a Node program that needs a workspace of 2048 MB or more; the +supervisor refuses to start it below that and says how to give the workspace more. Examples: spin agent my-workspace @@ -45,9 +45,10 @@ Flags: --timeout duration How long to wait for the workspace to be running; by default, until the control plane gives up on it Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false Use "spin agent [command] --help" for more information about a command. ``` @@ -72,9 +73,10 @@ Flags: -h, --help help for home Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false Use "spin agent home [command] --help" for more information about a command. ``` @@ -91,9 +93,10 @@ Flags: -h, --help help for delete Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` #### spin agent home list @@ -108,8 +111,9 @@ Flags: -h, --help help for list Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` diff --git a/src/content/docs/reference/cli/api-key.md b/src/content/docs/reference/cli/api-key.md index 1708b8b..a495492 100644 --- a/src/content/docs/reference/cli/api-key.md +++ b/src/content/docs/reference/cli/api-key.md @@ -29,9 +29,10 @@ Flags: -h, --help help for api-key Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false Use "spin api-key [command] --help" for more information about a command. ``` @@ -68,9 +69,10 @@ Flags: --scope strings Scopes for the key (can be repeated) Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin api-key list @@ -85,9 +87,10 @@ Flags: -h, --help help for list Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin api-key revoke @@ -103,8 +106,9 @@ Flags: -y, --yes Skip confirmation Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` diff --git a/src/content/docs/reference/cli/code.md b/src/content/docs/reference/cli/code.md index 49f2951..57fbfa8 100644 --- a/src/content/docs/reference/cli/code.md +++ b/src/content/docs/reference/cli/code.md @@ -29,23 +29,32 @@ Spin installs and configures neither extension. The server an installation publishes is Microsoft's, licensed for internal use only: one that sells workspaces to others leaves VS Code to download its own. +An editor that runs spin itself - the Spinbox extension - names its own commit with +--vscode-commit and --no-open: no local 'code' is looked for, the workspace is given that +commit's server as above, the SSH config is written, and nothing is opened. + Examples: spin code my-workspace spin code my-workspace /srv/app --start + spin code my-workspace --no-open --vscode-commit -o json Usage: spin code [path] [flags] Flags: - --editor string The editor's command, one with Remote-SSH or Open Remote - SSH installed (default "code") - -h, --help help for code - -i, --identity string Identity file (private key); default: the first of ~/.ssh/id_ed25519, id_rsa, id_ecdsa - --start Start the workspace first if it is stopped - --timeout duration How long to wait for the workspace to be running; by default, until the control plane gives up on it + --editor string The editor's command, one with Remote-SSH or Open Remote - SSH installed (default "code") + -h, --help help for code + -i, --identity string Identity file (private key); default: the first key this machine holds that your keyring lists + --no-open Write the SSH config and give the workspace the server, and open nothing; needs --vscode-commit + --start Start the workspace first if it is stopped + --timeout duration How long to wait for the workspace to be running; by default, until the control plane gives up on it + --vscode-commit string The commit of the VS Code that will connect, instead of asking a local 'code'; needs --no-open + --vscode-version string The version of that VS Code, which is only said; needs --vscode-commit Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` diff --git a/src/content/docs/reference/cli/cp.md b/src/content/docs/reference/cli/cp.md index 93d2666..34a5f50 100644 --- a/src/content/docs/reference/cli/cp.md +++ b/src/content/docs/reference/cli/cp.md @@ -31,8 +31,9 @@ Flags: -u, --user string User to copy as (default "root") Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` diff --git a/src/content/docs/reference/cli/exec.md b/src/content/docs/reference/cli/exec.md index 9ba5854..7d0336a 100644 --- a/src/content/docs/reference/cli/exec.md +++ b/src/content/docs/reference/cli/exec.md @@ -49,8 +49,9 @@ Flags: -w, --workdir string Directory to run the command in Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` diff --git a/src/content/docs/reference/cli/git.md b/src/content/docs/reference/cli/git.md index 6882311..05a452d 100644 --- a/src/content/docs/reference/cli/git.md +++ b/src/content/docs/reference/cli/git.md @@ -32,9 +32,10 @@ Flags: -h, --help help for git Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false Use "spin git [command] --help" for more information about a command. ``` @@ -58,9 +59,10 @@ Flags: --no-browser Do not open the forge's page in a browser Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin git disconnect @@ -77,9 +79,10 @@ Flags: -y, --yes Skip confirmation Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin git list @@ -94,9 +97,10 @@ Flags: -h, --help help for list Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin git repos @@ -112,8 +116,9 @@ Flags: -h, --help help for repos Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` diff --git a/src/content/docs/reference/cli/index.md b/src/content/docs/reference/cli/index.md index b101a48..7a6b901 100644 --- a/src/content/docs/reference/cli/index.md +++ b/src/content/docs/reference/cli/index.md @@ -43,16 +43,17 @@ Available Commands: ssh-config Make every workspace reachable with plain ssh, as the host spin. ssh-key Manage SSH keys team Manage teams - trust What this machine trusts of an installation + update Install the CLI of the release your installation runs version Print version information whoami Show current user info workspace Manage workspaces Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -h, --help help for spin - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -h, --help help for spin + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false Use "spin [command] --help" for more information about a command. ``` @@ -78,7 +79,7 @@ Use "spin [command] --help" for more information about a command. - [`spin ssh-config`](/reference/cli/ssh-config/): Make every workspace reachable with plain ssh, as the host spin. - [`spin ssh-key`](/reference/cli/ssh-key/): Manage SSH keys - [`spin team`](/reference/cli/team/): Manage teams -- [`spin trust`](/reference/cli/trust/): What this machine trusts of an installation +- [`spin update`](/reference/cli/update/): Install the CLI of the release your installation runs - [`spin version`](/reference/cli/version/): Print version information - [`spin whoami`](/reference/cli/whoami/): Show current user info - [`spin workspace`](/reference/cli/workspace/): Manage workspaces diff --git a/src/content/docs/reference/cli/login.md b/src/content/docs/reference/cli/login.md index ea9692d..d471782 100644 --- a/src/content/docs/reference/cli/login.md +++ b/src/content/docs/reference/cli/login.md @@ -26,8 +26,13 @@ There are two ways to authenticate: The server is --endpoint, else SPIN_ENDPOINT, else the one the profile is already logged in to, else https://app.spinbox.dev. +With --no-browser and -o json, the code is written as a first line of JSON before the wait +({verification_url, user_code, expires_in}), and the login as a second +({profile, endpoint, user}): a program shows the code itself and reads each line as it comes. + Examples: spin login # Sign in with a code, in a browser + spin login --no-browser -o json # the same, for a program that shows the code spin login --token-stdin < key.txt # Login with an API key (recommended for CI) printenv SPIN_KEY | spin login --token-stdin # the same, from a CI secret @@ -37,11 +42,13 @@ Usage: Flags: --endpoint string API endpoint URL (default: SPIN_ENDPOINT, the profile's, or https://app.spinbox.dev) -h, --help help for login + --no-browser do not open the code's page in a browser; with -o json, write the code as a first line of JSON --token-stdin read an API key (Settings > API Keys) from standard input instead of signing in with a code Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` diff --git a/src/content/docs/reference/cli/logout.md b/src/content/docs/reference/cli/logout.md index 46b278a..112a798 100644 --- a/src/content/docs/reference/cli/logout.md +++ b/src/content/docs/reference/cli/logout.md @@ -19,8 +19,9 @@ Flags: -h, --help help for logout Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` diff --git a/src/content/docs/reference/cli/open.md b/src/content/docs/reference/cli/open.md index b477326..ef145b4 100644 --- a/src/content/docs/reference/cli/open.md +++ b/src/content/docs/reference/cli/open.md @@ -18,8 +18,9 @@ workspace is made in --team, or your personal team. A repository no project has project of first ('spin project create'). The workspace is the project's shape, and its first access is signed here with a key of your -keyring, with the settings approved - the repository is one of them. It ends in 'spin ssh' -unless --no-connect. +keyring. Its repository is cloned once your settings name it at that ref: when they do not yet, +the settings you would sign are shown and asked about (--sign-settings: without asking), and +with no terminal to ask on they wait for 'spin sign'. It ends in 'spin ssh' unless --no-connect. Examples: spin open https://github.com/spin-stack/qboot @@ -34,13 +35,15 @@ Flags: --name string Workspace name (auto-generated if empty) --no-connect Create the workspace and print it, without connecting --project string The project to open, by slug, when more than one has the repository + --sign-settings Sign your settings, shown, without asking, when this workspace adds to them --team string The team the workspace is made in, by id, path or me (your personal team if empty) --timeout duration How long --wait waits; by default, until the control plane gives up on it --wait Return once the workspace is running, with --no-connect Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` diff --git a/src/content/docs/reference/cli/port.md b/src/content/docs/reference/cli/port.md index 287060a..d738ec3 100644 --- a/src/content/docs/reference/cli/port.md +++ b/src/content/docs/reference/cli/port.md @@ -28,9 +28,10 @@ Flags: -h, --help help for port Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false Use "spin port [command] --help" for more information about a command. ``` @@ -54,9 +55,10 @@ Flags: -h, --help help for access Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin port expose @@ -91,9 +93,10 @@ Flags: --https The port speaks TLS; the proxy does not verify its certificate, and its URL is {port}s- Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin port grant @@ -114,9 +117,10 @@ Flags: -h, --help help for grant Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin port list @@ -136,9 +140,10 @@ Flags: -h, --help help for list Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin port revoke @@ -156,9 +161,10 @@ Flags: -h, --help help for revoke Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin port unexpose @@ -179,8 +185,9 @@ Flags: -h, --help help for unexpose Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` diff --git a/src/content/docs/reference/cli/project.md b/src/content/docs/reference/cli/project.md index 3c7e9ad..06f7c41 100644 --- a/src/content/docs/reference/cli/project.md +++ b/src/content/docs/reference/cli/project.md @@ -37,9 +37,10 @@ Flags: -h, --help help for project Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false Use "spin project [command] --help" for more information about a command. ``` @@ -71,9 +72,10 @@ Flags: --slug string What it is named by in the installation (made from the name if empty) Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin project delete @@ -89,9 +91,10 @@ Flags: -y, --yes Skip confirmation Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin project list @@ -106,9 +109,10 @@ Flags: -h, --help help for list Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin project prebuild @@ -125,9 +129,10 @@ Flags: -h, --help help for prebuild Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin project prebuilds @@ -145,9 +150,10 @@ Flags: -h, --help help for prebuilds Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin project share @@ -171,9 +177,10 @@ Flags: --user stringArray A person who sees it, by id (repeatable) Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin project update @@ -200,8 +207,9 @@ Flags: --slug string What it is named by in the installation (made from the name if empty) Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` diff --git a/src/content/docs/reference/cli/settings.md b/src/content/docs/reference/cli/settings.md index 48b2ec1..e0ef53a 100644 --- a/src/content/docs/reference/cli/settings.md +++ b/src/content/docs/reference/cli/settings.md @@ -29,9 +29,10 @@ Flags: -h, --help help for settings Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false Use "spin settings [command] --help" for more information about a command. ``` @@ -57,9 +58,10 @@ Flags: --repo string Git repository URL Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin settings get @@ -74,9 +76,10 @@ Flags: -h, --help help for get Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin settings set @@ -101,9 +104,10 @@ Flags: -h, --help help for set Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin settings taskfile @@ -126,8 +130,9 @@ Flags: --validate string Validate a Taskfile without saving Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` diff --git a/src/content/docs/reference/cli/share.md b/src/content/docs/reference/cli/share.md index 66fcfab..a4b357d 100644 --- a/src/content/docs/reference/cli/share.md +++ b/src/content/docs/reference/cli/share.md @@ -32,9 +32,10 @@ Flags: -h, --help help for share Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false Use "spin share [command] --help" for more information about a command. ``` @@ -52,9 +53,10 @@ Flags: -h, --help help for add Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin share browse @@ -70,9 +72,10 @@ Flags: --public Include public snapshots (default true) Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin share list @@ -87,9 +90,10 @@ Flags: -h, --help help for list Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin share private @@ -104,9 +108,10 @@ Flags: -h, --help help for private Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin share public @@ -122,9 +127,10 @@ Flags: -h, --help help for public Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin share remove @@ -139,8 +145,9 @@ Flags: -h, --help help for remove Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` diff --git a/src/content/docs/reference/cli/sign.md b/src/content/docs/reference/cli/sign.md index be87c12..86b9dd6 100644 --- a/src/content/docs/reference/cli/sign.md +++ b/src/content/docs/reference/cli/sign.md @@ -14,7 +14,7 @@ Who logs in to a workspace is its access, which its owner signs with a key of th (the keys that sign for you), and its identity - the token it presents to a cloud, the certificate it signs a commit with - names its team as the team's roster says (its members, signed by its owners). The host a workspace runs on holds both to these, and the control plane -proposes each from what it holds and signs none of them: a control plane that is taken can +proposes each from what it holds and signs none of them: the control plane can neither let somebody into your workspace nor put one in your team. This shows each document waiting for your signature, and signs it with a key this machine holds @@ -35,8 +35,9 @@ Flags: -y, --yes sign without asking about each document Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` diff --git a/src/content/docs/reference/cli/smoke.md b/src/content/docs/reference/cli/smoke.md index 47dac61..26ded69 100644 --- a/src/content/docs/reference/cli/smoke.md +++ b/src/content/docs/reference/cli/smoke.md @@ -37,8 +37,9 @@ Flags: --timeout duration How long the scenarios may take, not counting the erase (default 15m0s) Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` diff --git a/src/content/docs/reference/cli/snapshot.md b/src/content/docs/reference/cli/snapshot.md index c5cca16..f9cb0b6 100644 --- a/src/content/docs/reference/cli/snapshot.md +++ b/src/content/docs/reference/cli/snapshot.md @@ -29,9 +29,10 @@ Flags: -h, --help help for snapshot Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false Use "spin snapshot [command] --help" for more information about a command. ``` @@ -54,9 +55,10 @@ Flags: --with-memory Keep the running processes too, so a restore resumes them Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin snapshot delete @@ -72,9 +74,10 @@ Flags: -y, --yes Skip confirmation Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin snapshot diff @@ -99,9 +102,10 @@ Flags: --under string Compare only this path of the filesystem, from its root (default: all of it) Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin snapshot list @@ -116,8 +120,9 @@ Flags: -h, --help help for list Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` diff --git a/src/content/docs/reference/cli/ssh-config.md b/src/content/docs/reference/cli/ssh-config.md index b4889bf..698ed0c 100644 --- a/src/content/docs/reference/cli/ssh-config.md +++ b/src/content/docs/reference/cli/ssh-config.md @@ -26,11 +26,12 @@ Usage: Flags: -h, --help help for ssh-config - -i, --identity string Identity file (private key); default: the first of ~/.ssh/id_ed25519, id_rsa, id_ecdsa + -i, --identity string Identity file (private key); default: the first key this machine holds that your keyring lists Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` diff --git a/src/content/docs/reference/cli/ssh-key.md b/src/content/docs/reference/cli/ssh-key.md index 64b3b93..5c4f4a7 100644 --- a/src/content/docs/reference/cli/ssh-key.md +++ b/src/content/docs/reference/cli/ssh-key.md @@ -30,9 +30,10 @@ Flags: -h, --help help for ssh-key Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false Use "spin ssh-key [command] --help" for more information about a command. ``` @@ -42,6 +43,11 @@ Use "spin ssh-key [command] --help" for more information about a command. ``` Upload an SSH public key that will be added to all your workspaces. +At a terminal, or with --wait, this goes on to get it signed: where this machine holds a key +your keyring lists it signs your keyring with it - when the keyring waiting is the one before +and this key, and nothing else; 'spin sign' shows and signs one that says more - and otherwise +it opens the page where your passkey signs and waits until you have. + Examples: spin ssh-key add laptop ~/.ssh/id_ed25519.pub spin ssh-key add work-key /path/to/key.pub @@ -51,13 +57,15 @@ Usage: spin ssh-key add [flags] Flags: - -h, --help help for add - --wait wait until your keyring lists the key, signed elsewhere + -h, --help help for add + --no-browser print the page where a passkey signs, instead of opening it + --wait wait until your keyring lists the key, signed elsewhere Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin ssh-key delete @@ -73,9 +81,10 @@ Flags: -y, --yes Skip confirmation Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin ssh-key list @@ -90,8 +99,9 @@ Flags: -h, --help help for list Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` diff --git a/src/content/docs/reference/cli/ssh.md b/src/content/docs/reference/cli/ssh.md index 800d8ee..ebcd39d 100644 --- a/src/content/docs/reference/cli/ssh.md +++ b/src/content/docs/reference/cli/ssh.md @@ -30,8 +30,9 @@ Flags: -u, --user string SSH username (certificates are issued for root today) (default "root") Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` diff --git a/src/content/docs/reference/cli/team.md b/src/content/docs/reference/cli/team.md index 0d55482..c9d9d63 100644 --- a/src/content/docs/reference/cli/team.md +++ b/src/content/docs/reference/cli/team.md @@ -32,9 +32,10 @@ Flags: -h, --help help for team Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false Use "spin team [command] --help" for more information about a command. ``` @@ -59,9 +60,10 @@ Flags: --slug string URL-friendly slug (auto-generated if empty) Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin team delete @@ -79,9 +81,10 @@ Flags: -y, --yes Skip confirmation Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin team get @@ -96,9 +99,10 @@ Flags: -h, --help help for get Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin team list @@ -115,9 +119,10 @@ Flags: --parent string Filter by parent team Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin team member @@ -139,9 +144,10 @@ Flags: -h, --help help for member Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false Use "spin team member [command] --help" for more information about a command. ``` @@ -159,9 +165,10 @@ Flags: --role string Role: owner, admin, member (default "member") Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` #### spin team member list @@ -176,9 +183,10 @@ Flags: -h, --help help for list Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` #### spin team member remove @@ -193,9 +201,10 @@ Flags: -h, --help help for remove Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` #### spin team member role @@ -210,9 +219,10 @@ Flags: -h, --help help for role Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin team policy @@ -236,9 +246,10 @@ Flags: -h, --help help for policy Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false Use "spin team policy [command] --help" for more information about a command. ``` @@ -256,9 +267,10 @@ Flags: -y, --yes Skip confirmation Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` #### spin team policy list @@ -273,9 +285,10 @@ Flags: -h, --help help for list Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` #### spin team policy set @@ -297,9 +310,10 @@ Flags: --rule stringArray Destinations and ports, as dest,dest:port,port (repeatable) Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin team secret @@ -324,9 +338,10 @@ Flags: -h, --help help for secret Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false Use "spin team secret [command] --help" for more information about a command. ``` @@ -344,9 +359,10 @@ Flags: -y, --yes Skip confirmation Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` #### spin team secret list @@ -361,9 +377,10 @@ Flags: -h, --help help for list Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` #### spin team secret set @@ -392,8 +409,9 @@ Flags: --ref string The ARN of the Secrets Manager secret or the Parameter Store parameter the team keeps the value in Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` diff --git a/src/content/docs/reference/cli/trust.md b/src/content/docs/reference/cli/trust.md deleted file mode 100644 index 51e0fd8..0000000 --- a/src/content/docs/reference/cli/trust.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: "spin trust" -description: "spin trust: What this machine trusts of an installation." -source: "spin:cmd/cli" -editUrl: false -sidebar: - order: 22 ---- - - - -``` -What this machine trusts of an installation - -Usage: - spin trust [flags] - spin trust [command] - -Available Commands: - egress-root Pin the installation's egress root this machine names in a workspace's word - -Flags: - -h, --help help for trust - -Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") - -Use "spin trust [command] --help" for more information about a command. -``` - -### spin trust egress-root - -``` -A workspace's guest trusts its host's egress proxy only by the root its owner's word names, -and this machine names only the root it pinned for the installation: the first one the control -plane offered. Pin another - the installation's root was changed - by the SHA-256 that -'spin-controlplane egress-root' prints on the control plane's machine. Colons and capitals, as -openssl prints a fingerprint, are taken. - -A workspace's word names the new root once signed again: 'spin workspace approve-egress-root'. - -Usage: - spin trust egress-root [flags] - -Flags: - -h, --help help for egress-root - -Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") -``` - diff --git a/src/content/docs/reference/cli/update.md b/src/content/docs/reference/cli/update.md new file mode 100644 index 0000000..504bdb6 --- /dev/null +++ b/src/content/docs/reference/cli/update.md @@ -0,0 +1,32 @@ +--- +title: "spin update" +description: "spin update: Install the CLI of the release your installation runs." +source: "spin:cmd/cli" +editUrl: false +sidebar: + order: 22 +--- + + + +``` +An installation serves a CLI of its own release alone. This asks yours which it runs, pulls +that release's CLI, and replaces this one once the release's signature and provenance say it is +what the release workflow built. Whichever release it runs is the one installed, an older one +included: it is the only one it serves. + +A command the installation refuses for a CLI behind it does this by itself and runs again. + +Usage: + spin update [flags] + +Flags: + -h, --help help for update + +Global Flags: + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false +``` + diff --git a/src/content/docs/reference/cli/version.md b/src/content/docs/reference/cli/version.md index 0236a1c..84df3f9 100644 --- a/src/content/docs/reference/cli/version.md +++ b/src/content/docs/reference/cli/version.md @@ -19,8 +19,9 @@ Flags: -h, --help help for version Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` diff --git a/src/content/docs/reference/cli/whoami.md b/src/content/docs/reference/cli/whoami.md index 01c94ec..65370b9 100644 --- a/src/content/docs/reference/cli/whoami.md +++ b/src/content/docs/reference/cli/whoami.md @@ -19,8 +19,9 @@ Flags: -h, --help help for whoami Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` diff --git a/src/content/docs/reference/cli/workspace.md b/src/content/docs/reference/cli/workspace.md index 3fc0d2f..62d4d5c 100644 --- a/src/content/docs/reference/cli/workspace.md +++ b/src/content/docs/reference/cli/workspace.md @@ -20,124 +20,52 @@ Aliases: workspace, ws Available Commands: - approve-egress-root Let the workspace trust the installation's egress root - approve-settings Approve the startup settings the workspace is handed - audiences Who the workspace's identity may be given for, as its owner's word says - bandwidth Set what a workspace's network carries each way (admin) - clone Clone a running workspace - console What the workspace's machine printed to its serial console - create Create a new workspace - delete Delete a workspace - deleted List your workspaces in the trash - denials What a workspace attempted past its policy (admin) - egress What a workspace has reached beyond this installation - get Get workspace details - grant Give a workspace more cores and memory of its own - guests The people who log in to a workspace besides its owner - history Show workspace state change history - keep Keep a running workspace awake for a while - list List your workspaces - logs Search what the workspace's machine printed to its console - logs-consent Say whether the workspace's journal and console may be collected - move Move a running workspace to another host - policies The network policies a workspace can be created with - quarantine Hold a workspace in quarantine (admin) - recover Re-home a workspace whose host is gone - release Give back what a workspace was granted - reset Put a stopped workspace's disk back to what it was created from - restore Put a stopped workspace's disk back to a snapshot, or to what it was created from - retag Change which network policies a workspace runs under - sign Sign the workspace's next access: who logs in, as you invited them - start Start a stopped workspace - status Why a workspace is not behaving - stop Stop a running workspace - suspend Put a running workspace down with its processes where they are - threads The agent's chats, as the workspace last reported them - undelete Take a workspace out of the trash, stopped - unquarantine Release a quarantined workspace (admin) - update Update workspace properties - watch Record where a workspace connects, into its logs + bandwidth Set what a workspace's network carries each way (admin) + clone Clone a running workspace + console What the workspace's machine printed to its serial console + create Create a new workspace + delete Delete a workspace + deleted List your workspaces in the trash + denials What a workspace attempted past its policy (admin) + egress What a workspace has reached beyond this installation + get Get workspace details + grant Give a workspace more cores and memory of its own + guests The people who log in to a workspace besides its owner + history Show workspace state change history + keep Keep a running workspace awake for a while + list List your workspaces + logs Search what the workspace's machine printed to its console + move Move a running workspace to another host + policies The network policies a workspace can be created with + quarantine Hold a workspace in quarantine (admin) + recover Re-home a workspace whose host is gone + release Give back what a workspace was granted + reset Put a stopped workspace's disk back to what it was created from + restore Put a stopped workspace's disk back to a snapshot, or to what it was created from + retag Change which network policies a workspace runs under + sign Sign the workspace's next access: who logs in, as you invited them + start Start a stopped workspace + status Why a workspace is not behaving + stop Stop a running workspace + suspend Put a running workspace down with its processes where they are + threads The agent's chats, as the workspace last reported them + undelete Take a workspace out of the trash, stopped + unquarantine Release a quarantined workspace (admin) + update Update workspace properties + watch Record where a workspace connects, into its logs Flags: -h, --help help for workspace Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false Use "spin workspace [command] --help" for more information about a command. ``` -### spin workspace approve-egress-root - -``` -A workspace's guest puts the installation's egress root in its trust store - the CA its host's -egress proxy stands in for brokered hosts with - only while its owner's word names it: a root -there reads what the guest's TLS clients send through the proxy. This signs a word naming the -root the control plane offers, once held to the one this machine pinned for the installation -(the first offered; 'spin trust egress-root' pins another). - -Usage: - spin workspace approve-egress-root [flags] - -Flags: - -h, --help help for approve-egress-root - -Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") -``` - -### spin workspace approve-settings - -``` -A workspace applies its startup settings - dotfiles and the command that installs them, the -login shell, the environment, the editor's settings and the Taskfile - only as its access -approves them, by their digest. This shows the settings the control plane would hand it now, -and signs an access approving exactly those: settings changed afterwards, by anyone, are not -applied until approved again. - -Usage: - spin workspace approve-settings [flags] - -Flags: - -h, --help help for approve-settings - -y, --yes Skip confirmation - -Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") -``` - -### spin workspace audiences - -``` -A host gives a workspace's identity token - to the guest, or through its egress proxy - only -for an audience its owner's word names and the installation allows: the installation's list is -the control plane's to write, so it alone never widens who the identity reaches. - -With no flags this shows the word's audiences and the installation's. --add and --remove sign -the owner's next word naming more or fewer; --any signs one naming any audience the -installation allows, which trusts the installation's list. - -Usage: - spin workspace audiences [flags] - -Flags: - --add strings an audience to name - --any name any audience the installation allows - -h, --help help for audiences - --remove strings an audience to name no more - -Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") -``` - ### spin workspace bandwidth ``` @@ -156,9 +84,10 @@ Flags: -h, --help help for bandwidth Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace clone @@ -185,9 +114,10 @@ Flags: --wait Return once the clone is running Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace console @@ -209,9 +139,10 @@ Flags: --lines int32 How many lines from the end (default 200) Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace create @@ -223,14 +154,18 @@ preset the installation offers; without --preset, the installation's default. Every workspace answers to its access, which you sign here with a key of your keyring (the keys you registered, 'spin ssh-key add', and signed, 'spin sign'): who logs in - you, and the guests -you invite - whether logs leave the workspace and which settings it applies. The host it runs -on lets a key in only by it, and the control plane cannot write one. Settings are applied once -you approve them (--approve-settings, or 'spin workspace approve-settings'). +you invite. The host it runs on lets a key in only by it, and the control plane cannot write one. + +What it applies of yours - dotfiles, shell, environment, editor settings, Taskfile, this +workspace's own --env, and the repository a project clones - is your settings, signed once for +every workspace ('spin sign'): its host applies only what a key of your keyring signed. A +workspace that adds to them - a project or a ref you have not signed, an --env of its own - shows +what you would sign and asks (--sign-settings: without asking); until you sign, it applies what +you signed before. A project (--project) is the workspace's shape - its image, preset and network policies - and the repository its guest clones into /workspace/, at --ref or the project's own; -the workspace is made in --team, or your personal team. Opening one approves the settings, since -the repository is one of them. A project whose repository is on GitHub opens once you have +the workspace is made in --team, or your personal team. A project whose repository is on GitHub opens once you have connected your GitHub account (Settings → Git in the dashboard). Examples: @@ -245,7 +180,6 @@ Usage: Flags: --agent-home string An agent's home of yours to mount, by id (spin agent home list): the chats of a workspace since erased - --approve-settings Show your startup settings and approve them in the first access --env strings Environment variables (KEY=VALUE) --from-snapshot string Start from a snapshot instead of an image -h, --help help for create @@ -255,14 +189,16 @@ Flags: --preset string The preset it is sized by, by name (default: the installation's) --project string A project to open, by slug: its image, preset and policies, and its repository cloned --ref string The branch or tag to open the project at (default: the project's) + --sign-settings Sign your settings, shown, without asking, when this workspace adds to them --team string The team, by id, path or me (your personal team if empty) --timeout duration How long --wait waits; by default, until the control plane gives up on it --wait Return once the workspace is running Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace delete @@ -282,9 +218,10 @@ Flags: -y, --yes Skip confirmation Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace deleted @@ -299,9 +236,10 @@ Flags: -h, --help help for deleted Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace denials @@ -319,9 +257,10 @@ Flags: --limit int32 How many of the newest to read (default 100) Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace egress @@ -342,9 +281,10 @@ Flags: -h, --help help for egress Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace get @@ -359,9 +299,10 @@ Flags: -h, --help help for get Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace grant @@ -396,9 +337,10 @@ Flags: --move Move it to a host with room when its own has none (it is paused while it moves) Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace guests @@ -421,9 +363,10 @@ Flags: -h, --help help for guests Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false Use "spin workspace guests [command] --help" for more information about a command. ``` @@ -440,9 +383,10 @@ Flags: -h, --help help for add Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` #### spin workspace guests list @@ -457,9 +401,10 @@ Flags: -h, --help help for list Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` #### spin workspace guests remove @@ -475,9 +420,10 @@ Flags: -h, --help help for remove Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace history @@ -493,9 +439,10 @@ Flags: --limit int32 Number of events to show (default 50) Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace keep @@ -514,9 +461,10 @@ Flags: -h, --help help for keep Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace list @@ -532,9 +480,10 @@ Flags: --state string Filter by state (running, stopped, etc.) Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace logs @@ -559,27 +508,10 @@ Flags: --since duration how far back to look, at most 744h (31 days) (default 1h0m0s) Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") -``` - -### spin workspace logs-consent - -``` -A workspace's journal and its console leave it only while its access consents, and the -installation collects them: either can say no. The owner signs the consent, on this machine. - -Usage: - spin workspace logs-consent [flags] - -Flags: - -h, --help help for logs-consent - -Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace move @@ -601,9 +533,10 @@ Flags: -h, --help help for move Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace policies @@ -624,9 +557,10 @@ Flags: -h, --help help for policies Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace quarantine @@ -646,9 +580,10 @@ Flags: -y, --yes Skip confirmation Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace recover @@ -670,9 +605,10 @@ Flags: -h, --help help for recover Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace release @@ -689,9 +625,10 @@ Flags: -h, --help help for release Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace reset @@ -714,9 +651,10 @@ Flags: -y, --yes Skip confirmation Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace restore @@ -742,9 +680,10 @@ Flags: --with-memory Resume the snapshot's processes too; the workspace may be running Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace retag @@ -774,9 +713,10 @@ Flags: --network-tag strings Network policy to run under, by name (repeatable); the whole set, not an addition Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace sign @@ -784,9 +724,8 @@ Global Flags: ``` A workspace lets in whoever its access names - you, and the guests you invited - and nobody else: its host holds every login to it, with each person's own keyring. This signs the next -access with a key of your keyring, on this machine, naming the guests as they are now and -keeping every consent as it was. A workspace you created and never signed lets nobody in -until you do. +access with a key of your keyring, on this machine, naming the guests as they are now. A +workspace you created and never signed lets nobody in until you do. Usage: spin workspace sign [flags] @@ -795,9 +734,10 @@ Flags: -h, --help help for sign Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace start @@ -819,9 +759,10 @@ Flags: --wait Return once the workspace is running Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace status @@ -841,9 +782,10 @@ Flags: -h, --help help for status Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace stop @@ -864,9 +806,10 @@ Flags: --wait Return once the workspace is stopped Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace suspend @@ -890,9 +833,10 @@ Flags: -h, --help help for suspend Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace threads @@ -902,10 +846,6 @@ The agent's threads - T3 Code's chats - as the workspace's supervisor last repor newest first: a title, the directory it works in, the model, and when it last moved. Never a message: a chat is read in T3 Code, over your own session (spin agent). -The supervisor reports the index only while the workspace's access consents to its logs -leaving the machine (spin workspace logs-consent); a workspace whose owner has not says -nothing here. - Usage: spin workspace threads [flags] @@ -913,9 +853,10 @@ Flags: -h, --help help for threads Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace undelete @@ -932,9 +873,10 @@ Flags: -h, --help help for undelete Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace unquarantine @@ -953,9 +895,10 @@ Flags: -y, --yes Skip confirmation Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace update @@ -981,9 +924,10 @@ Flags: --wake-on-access Resume it, when suspended, for a signed-in visitor of one of its ports (never an anonymous one) Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` ### spin workspace watch @@ -1005,8 +949,9 @@ Flags: --off Stop recording where the workspace connects Global Flags: - --config string config file (default is $HOME/.spin/config.yaml) - -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") - --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --config string config file (default is $HOME/.spin/config.yaml) + -o, --output string text for a person, or json: one document of what the API answered, and no prose (default "text") + --profile string named profile to use; SPIN_PROFILE names it when this flag does not (default "default") + --traceparent string the W3C traceparent of the span this command is part of; its own span is sent to the installation unless the profile says telemetry: false ``` diff --git a/src/content/docs/reference/security/known-gaps.md b/src/content/docs/reference/security/known-gaps.md index d28db07..22ba521 100644 --- a/src/content/docs/reference/security/known-gaps.md +++ b/src/content/docs/reference/security/known-gaps.md @@ -9,7 +9,7 @@ sidebar: -The open items of Spinbox's security model, from spin's [`docs/security/README.md`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/docs/security/README.md) at `2cfbcd74d`. The numbers are [its rules](/reference/security/rules/). +The open items of Spinbox's security model, from spin's [`docs/security/README.md`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/docs/security/README.md) at `3cb9bb55f`. The numbers are [its rules](/reference/security/rules/). What no line keeps yet. Each is a design change, not a patch, which is why it is here. @@ -40,13 +40,10 @@ What no line keeps yet. Each is a design change, not a patch, which is why it is and HEADs under its own subtree that no restore takes, each counted as it is passed over and every request in the bucket's access log (I8). - **A key a host was given opens what it sealed until the volume is re-keyed.** A volume's key - never turns, and an honest host forgets it when the volume leaves; a taken one keeps it. Revoking + never turns, and an honest host forgets it when the volume leaves; one running other code keeps it. Revoking a host marks every volume it was granted for a re-key, which runs once the workspace is stopped: until then the layers that key opens are open to whoever holds it, and the re-key deletes the volume's snapshots with it, being exactly what that key opens. -- **The storage layer holds nothing against a control plane that is taken.** It mints every - credential and grants every key: one that is taken clones any snapshot to a workspace of its own - on an attested runner, and comes in with a keyring of its own. - **A move between a detach and its attach is the old host's.** A grant is made over the HEAD the volume's history reaches when the control plane places it, so what the host it left wrote in that window - seconds, when the move is one `RecoverWorkspace` - is history the new holder starts @@ -64,45 +61,48 @@ What no line keeps yet. Each is a design change, not a patch, which is why it is which carries Quickwit's own services beside the logs it is sent, and Grafana can write samples as well as read them. Root on the control plane's machine can drop the table; that root is the installation already. -- **I17, I18 and I19 do not hold against a control plane that uses a host.** It opens a root shell - on any host (`OpenHostShellCommand`): both keys are its own, and the host checks only the time and - the keys' shape. Emptying the host first, the approval and the recording are the control plane's - own code, which one that is taken skips. Root on a host reads and writes every workspace on it, - memory included, and is answered by the key service as that host is. Holding the shell to a key - the control plane does not have is not built: a lost key would leave a host with no way in during - an incident, and it would only narrow a control plane already taken (`CLAUDE.md`). -- **The owner's word names no disk.** A host takes the spec's volume over the one it held, since a - restore changes it, and a word says nothing of the volume. So a control plane that is taken can - start a person's workspace on a disk it chose, whose code then runs as that workspace: it logs in - as nobody, and pushes and calls through the egress proxy as the owner. -- **A taken control plane opens every connected person's forge tokens.** It holds the access and - refresh tokens sealed under its own key, and with them acts on the forge directly, as each person, - within the app's permissions (contents and pull requests, read and write) and the repositories - that person reaches where the app is installed. Nothing on a host stands in the way, and the app - installed on selected repositories and the forge's branch rules are the only limit. A refresh - token it copied can outlive it until the person's authorization ends. -- **Machines the control plane's role starts.** Auto Scaling asks that role for `ec2:RunInstances` - on the runners' launch template, and under that grant a call that names the template and other - user data starts the machine with the other user data, tried on AWS on 2026-11-04; holding the - instance to `ec2:IsLaunchTemplateResource` did not stop it. User data is not measured, so such a - machine might attest as a runner under a document the control plane chose; whether it does has - not been tried. It is told, not stopped: a rule emails `security_emails` within minutes of the - call. +- **Which release of the CLI a person runs.** A CLI behind its installation replaces itself with + the release the control plane names (`internal/selfupdate`), and `spin update` does so for any + release it names, an older one included. Only what the release workflow signed and attested of + that very version is installed, checked offline before it replaces anything, so a control plane + cannot have a CLI run a binary of its own. It can have `spin update` install an older signed one, + with whatever that one got wrong; the automatic update only ever moves forward. +- **A workspace's owner sees who opens its pages.** Signing in to a workspace's host gives that host a + session for that workspace alone, which the API refuses, and a page on the host can read how it got + there. So its owner can act as the visitor on their own workspace and nowhere else, and learns + that the person visited. +- **Workspaces are one site to a browser unless `ws.` is on the public suffix list.** A + dashboard cookie is host-only and the API refuses it from another origin, and the proxy asks as + nobody for another workspace's page, by `Origin`, `Sec-Fetch-Site` and `Referer`. A link followed + from another workspace still carries the visitor's session on the workspace it opens, as a top-level + navigation has to: `SameSite=Lax` sends it on a link from any site, so that listing does not change + it. What the listing does change is what a tenant's page can do with cookies of its own: until + then it can set one with `Domain=`, or `Domain=ws.`, which reaches the dashboard's + host and every other workspace. A browser that sends no `Sec-Fetch-Site` is not told apart from a tool on a plain `GET`. Sessions issued + through a workspace before this release can reach the whole account until they expire. - **I17 and I18 hold against an operator, not against the tenant, nor a guest.** Root in a guest is anybody the access lets in - its owner and each guest alike: it can rewrite the drop-in and the supervisor's answers. Sealing keeps everyone else out; it does not keep the people let in from the machine they were let into. -- **A browser session logs in for 12 h with nobody asked.** Code running on the terminal's origin - - already trusted with every signature there - or malware in the browser uses its session key - without a prompt until the grant ends; ending the session (`#/session`) drops the key, and taking - the passkey that signed it out of the keyring ends the grant at every host within `roster.Fresh`. +- **A browser session logs in for 7 days, and changes an access, with nobody asked.** Code running on + the terminal's origin - already trusted with every signature there - or malware in the browser uses + its session key without a prompt until the grant ends; ending the session (`#/session`) drops the + key, and taking the passkey that signed it out of the keyring ends the grant at every host within + `roster.Fresh`. Past the first, the key also signs any access that lets nobody new in - guests + taken out - by a click at most, and none of it ends with the grant. It signs no settings: those + take a key of the keyring (I18). A host reads an + access for the workspace's life, and a word's own date is the key's to write, so holding it to + the grant is only the control plane's, when it keeps it (`SetOwnerWord`): a taken one keeps what + such code signs after the grant ended, and it stands while the passkey stays in the keyring. The + key stays in the browser until the session ends. What a host holds a session key's access to is the people it names, against the + word below it (`ownerword.highest`), so no script or control plane lets anybody in with it. A first access the key signed is read for the workspace's life, held only to having been taken - while the grant held (`SetOwnerWord`). A taken control plane holds no key that signs one, but it + while the grant held (`SetOwnerWord`). The control plane holds no key that signs one, but it serves the page that frames the agent's: while a grant holds and the dashboard is open, it can make a workspace in the person's name and frame it, and the session key signs that first access - with no prompt and nothing on screen. It gets a word naming the image and team it chose and the - installation's audiences, so identity tokens naming the person for a disk it chose; it gets no - login, guests, settings or logs (`ownerword.Word.Minimal`) and none of the workspaces that have - a word. A link to a terminal of its own got the same for one click, so this was accepted. A script + with no prompt and nothing on screen. It gets a word naming the image and team it chose, so + identity tokens naming the person for a disk it chose, for any audience the installation allows; + it gets no login, guests or settings (`ownerword.Word.Minimal`, I18) and none of the workspaces + that have a word. A link to a terminal of its own got the same for one click, so this was accepted. A script on the dashboard's origin reaches the same, for an image the installation allows. - **Taking a passkey out of a keyring locks what it signed.** A workspace whose newest access that passkey or its session key signed lets nobody in until its owner signs it again with another key, @@ -110,7 +110,7 @@ What no line keeps yet. Each is a design change, not a patch, which is why it is workspaces hang on one passkey, so the page leads its owner to that signature (`enter`). An owner whose keyring started anew cannot sign one, and recovers the workspace instead. - **A person's first keyring is whoever signs it first.** A keyring's first version is taken as it - is signed: nothing names a person's keys before it. A stolen account, or a taken control plane, + is signed: nothing names a person's keys before it. A stolen account, or a control plane running someone else's code, can sign one for somebody who has not yet, list the person's passkey beside its own when they register one, and log in to all they make. It holds for anybody whose first keyring was signed before: the chain is then theirs. @@ -118,64 +118,133 @@ What no line keeps yet. Each is a design change, not a patch, which is why it is account, or their password manager, holds their passkey and signs as them: the same as the person to every host. It is a third party outside the control plane and the operator, accepted so that a person has one passkey rather than one per browser. A security key stays on the device. -- **A new browser is one touch from pinning an egress root.** With a synced passkey it no longer - waits for another device, and pins the first root offered (`heldRoot`), so a control plane taken - before then has it trust its own. The person's way to check is unchanged: `spin-controlplane - egress-root`. - **What is typed in an overlaid Agent frame reaches T3 Code.** The dashboard frames the agent's page and can lay words over it, as it cannot over the routes that sign: typing goes to the client, as the agent's user. A terminal stays in a tab of its own for this reason, a shell there being root. -- **A taken control plane can start a person's keyring anew.** It does through the account what a - person who lost every key does (`StartKeyringAnew`), and a keyring started anew is somebody no - access or roster signed before names - so it gets into none of their workspaces and none of their - teams of more than one - but it can make new workspaces that answer to it, and sign the person's - own team of one again (`roster.Roster.Start`), whose identity then names those workspaces. The CLI - and the terminal show a keyring started anew before it is signed; nothing tells a person their - account was used to start one. - **A guest is let into the guest by the same certificate as the owner.** The host decides who logs in, not what a login may do: a guest is root, and changes nothing the control plane holds - `middleware.guestMay` - but can change the machine itself. Sharing a workspace is trusting the guest with it. -- **A control plane can withhold the owner's newest access.** It carries every one, so one taken - before an access reaches the bucket can keep it from the bucket and the host - a guest taken out - logs in until the host reads it - and answer the owner's client with an older one. An access the - bucket has is past withholding: the host reads it at every login. A client signs nothing over an - access behind the newest it signed itself (`~/.spin/words`, the terminal origin's storage); a - client that signed nothing yet of the workspace has no newest to hold it to. -- **The egress root is trusted on first use.** An owner's client pins the first root an - installation offers (`~/.spin/egress-roots`, the terminal origin's storage), so a control plane - that is taken can offer its own to a client that never pinned one. A person closes that by - comparing the fingerprint with `spin-controlplane egress-root` on the control plane's machine. - A guest whose access names no root, or another, trusts none, and its brokered hosts fail - TLS: denial, not a read. -- **I21 holds against a confused deputy, not a taken control plane.** The control plane tags the - session, so one that is taken tags it with any team, and it holds every value it reads in the - clear, as it does a sealed one. The tag is only as good as who may tag a secret: a principal of - the account that can tag one `spin-team-id` hands it to that team. - Its role takes the control plane's credentials from anywhere while they last, so a reference is - read off the machine where a sealed value is not: that needs the attested key. +- **A person's agent CLI credentials are one, for all their workspaces.** Claude Code's and Codex's + credentials files are kept as the person's (`agent_credentials`, sealed) and handed to every + workspace they own, so one login signs in each (`supervisorserver.pushCredentials`, + `agentcredentials.Keeper`). So whoever runs code in one of them - the agent itself, led there by + what it read, or a dependency the workspace installed - holds the provider token of every one, and + a change it sends replaces the copy they all use, until the person logs out or revokes it at the + provider. Only a workspace its owner's alone is handed any or has one taken from it + (`workspaces.owners_alone`, `supervisorserver.holdsCredentials`): made of an image, of a + snapshot or clone of a workspace of theirs that is so too, or of the prebuild of a project they + may open, mounting an agent's home only such workspaces mounted (`agent_volumes.owners_alone`), + never naming a guest, and never a prebuild's build. A prebuild's disk holds what the + repository's code did in its build, which is no more than that code does as root in a workspace + opened straight from the repository; the build, which nobody watches and every member opens, is + handed nothing. A copy of another person's snapshot, and every workspace and home made before + the mark was kept, get none, and the person signs in there as before. Its + supervisor takes out what it held once the access names a guest (`handler.TakeOwnerWord`). What + does not leave with the files: a guest named while the agent was signed in may read what the + machine kept of them - freed blocks of the agent's home, and the memory of a CLI the agent's + stopped server did not end. +- **A guest trusts the egress root its control plane hands it.** Every registration hands the + installation's root, and the guest puts it in its trust store (`handler.InstallEgressCA`): a root + there reads what the guest's TLS clients send through a proxy that holds it. Only the egress proxy + of the host the workspace runs on is issued under it, and that host is one the control plane can + open a root shell on anyway; nothing an owner says narrows it. +- **Logs leave as the installation says.** A guest's journal and a machine's console are collected + while the installation's policy collects them (`LogCollection`, `HostPolicy.collect_console`), + and the agent's thread index is reported always: titles, paths and times, never a message. An owner + has no say over it, so an installation admin's session - stolen or not - reads every collected + journal: a decision, not an oversight. +- **A key taken out of a keyring works for up to `roster.Fresh` (5 minutes) more.** A host reads a + keyring again when what it holds is older than that, so a key taken out still logs in, and settings + it signed still apply, at a host that read the keyring just before. +- **A repository approval is not withdrawn.** Settings name each repository a workspace of the person + opened, and signing new settings is the only way to drop one: nothing takes an approval back + without the person's key, and nothing reminds them that one stands. - **The terminal's code is trusted as the proxy serves it.** `term.`, and the agent's client it frames at `agents.`, are the release's signed files on the proxy image's verity - root, under a Caddyfile spin-boot carries, so a control plane that is taken changes neither; a - proxy taken at run time serves any code that holds a session and asks the passkey. + root, under a Caddyfile spin-boot carries, so the control plane changes neither; a + proxy running other code serves any code that holds a session and asks the passkey. - **The published key set is the identity key's first version, as the proxy serves it.** `id.` is written on the proxy from the first version of `identity/issuer.json` and its CA, - which no role may delete, so a control plane that is taken and writes another key publishes - nothing of it; a proxy taken at run time publishes any key set. A self-hosted installation + which no role may delete, so another key the control plane writes publishes + nothing; a proxy running other code publishes any key set. A self-hosted installation serves none. - **I19 holds the identity key to the image a host booted, not to the host.** Every host shares - the key, because the published key set is one key: a runner taken at run time signs for any + the key, because the published key set is one key: a runner running other code signs for any subject. A self-hosted installation has no key service, and its control plane keeps the key it grants. - **A keyring and a roster are trusted from their first version.** A version is signed by a key the one before trusts, and kept under the bucket's lock in GOVERNANCE, which the account's root - can lift. A user or a team made while the control plane is taken starts a chain whose first + can lift. A user or a team made by a control plane running someone else's code starts a chain whose first version the control plane can sign - and a team it makes is its own, which nothing trusts. A version already kept is not written over: on AWS the bucket's policy refuses a write under `rosters/` without `If-None-Match`. A store with no such policy has only the client's word for it. + +## What this does not protect + +The control plane holds what it needs to serve people. What follows is what it could do with that if +someone ran their own code with its permissions. This is an assumption the design is checked against, +not a finding: no way of doing that is known, and no outside test has looked for one yet. Below, "it" +is such a control plane. + +- **The storage layer holds nothing against it.** The control plane mints every credential and + grants every key, so it could clone any snapshot to a workspace of its own on an attested runner, + and come in with a keyring of its own. +- **I17, I18 and I19 do not hold against a control plane that uses a host.** It can open a root shell + on any host (`OpenHostShellCommand`): both keys are its own, and the host checks only the time and + the keys' shape. Emptying the host first, the approval and the recording are the control plane's + own code, which other code would skip. Root on a host reads and writes every workspace on it, + memory included, and is answered by the key service as that host is. Holding the shell to a key + the control plane does not have is not built: a lost key would leave a host with no way in during + an incident, and it would only narrow what is described here (`CLAUDE.md`). +- **The owner's word names no disk.** A host takes the spec's volume over the one it held, since a + restore changes it, and a word says nothing of the volume. So the control plane could + start a person's workspace on a disk it chose, whose code then runs as that workspace: it logs in + as nobody, and pushes and calls through the egress proxy as the owner. +- **It can open every connected person's forge tokens.** The control plane holds the access and + refresh tokens sealed under its own key, and with them could act on the forge directly, as each person, + within the app's permissions (contents and pull requests, read and write) and the repositories + that person reaches where the app is installed. Nothing on a host stands in the way, and the app + installed on selected repositories and the forge's branch rules are the only limit. A refresh + token it copied can outlive it until the person's authorization ends. +- **It can open every person's agent CLI credentials.** Their Claude Code and Codex tokens are + sealed under its key (`agent_credentials`), as the forge's are, and with them it could use each + person's provider account directly, until the person logs out or revokes them at the provider. +- **Machines the control plane's role starts.** Auto Scaling asks that role for `ec2:RunInstances` + on the runners' launch template, and under that grant a call that names the template and other + user data starts the machine with the other user data, tried on AWS on 2026-11-04; holding the + instance to `ec2:IsLaunchTemplateResource` did not stop it. User data is not measured, so such a + machine might attest as a runner under a document the control plane chose; whether it does has + not been tried. It is told, not stopped: a rule emails `security_emails` within minutes of the + call. +- **It can start a person's keyring anew.** It does through the account what a + person who lost every key does (`StartKeyringAnew`), and a keyring started anew is somebody no + access or roster signed before names - so it gets into none of their workspaces and none of their + teams of more than one - but it can make new workspaces that answer to it, and sign the person's + own team of one again (`roster.Roster.Start`), whose identity then names those workspaces. The CLI + and the terminal show a keyring started anew before it is signed; nothing tells a person their + account was used to start one. +- **A control plane can withhold the owner's newest access.** It carries every one, so before an + access reaches the bucket it can keep it from the bucket and the host - a guest taken out + logs in until the host reads it - and answer the owner's client with an older one. An access the + bucket has is past withholding: the host reads it at every login, and takes no lower counter over + it. A client builds the next access on what the control plane answers and keeps no record of its + own, so over an access withheld before it reached the bucket it signs the guests it is shown - + which the CLI prints and the terminal lists before anything is signed. +- **It can hand a host settings its owner signed before.** The host is handed the owner's + settings as the control plane keeps them, and holds them to the owner's keyring, not to being the + newest the owner signed: older settings, signed with a key the keyring still holds, are applied as + readily. It also says whether a workspace is its owner's alone, which withholds their own + settings where it says no and nothing where it says yes, and which prebuild a disk came from, + whose claim the host still holds the checkout to. +- **I21 holds against a confused deputy, not this.** The control plane tags the + session, so other code in it could tag it with any team, and it holds every value it reads in the + clear, as it does a sealed one. The tag is only as good as who may tag a secret: a principal of + the account that can tag one `spin-team-id` hands it to that team. + Its role takes the control plane's credentials from anywhere while they last, so a reference is + read off the machine where a sealed value is not: that needs the attested key. - **The domain an identity is named under is the control plane's word.** It comes with the host's - policy, and a taken control plane can change it - which a relying party refuses, since the - issuer it names publishes another key set: denial, not a widening. An owner who names - `"*"` in their word trusts the installation's list of audiences, which a taken control plane - writes. A member of a parent team is no member of a team below it: a roster names a team's own + policy, and it can change it - which a relying party refuses, since the + issuer it names publishes another key set: denial, not a widening. Who an identity is given for is + the installation's list of audiences alone, which the control plane writes. A member of a parent team is no member of a team below it: a roster names a team's own members. diff --git a/src/content/docs/reference/security/rules.md b/src/content/docs/reference/security/rules.md index 283fd02..1803a89 100644 --- a/src/content/docs/reference/security/rules.md +++ b/src/content/docs/reference/security/rules.md @@ -9,7 +9,7 @@ sidebar: -The rules every entry point must keep, from spin's [`docs/security/README.md`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/docs/security/README.md) at `2cfbcd74d`. Code cites a rule's number at the line that keeps it. **Gate** is what fails a build when the rule is broken; *none* marks a rule kept only by each place remembering it. What is still open is on [Known gaps](/reference/security/known-gaps/). +The rules every entry point must keep, from spin's [`docs/security/README.md`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/docs/security/README.md) at `3cb9bb55f`. Code cites a rule's number at the line that keeps it. **Gate** is what fails a build when the rule is broken; *none* marks a rule kept only by each place remembering it. What is still open is on [Known gaps](/reference/security/known-gaps/). | # | Rule | Gate | |---|---|---| @@ -29,9 +29,10 @@ The rules every entry point must keep, from spin's [`docs/security/README.md`](h | I14 | A machine's QEMU reaches only what it is handed, and holds only what it is bounded to - a core included. | `TestAProductionInstallationPlacesOnlyOnIsolatedHosts`, `TestEveryIsolationIsAskedOnce`, `TestAHostSaysItKeepsWhatItCanGiveAMachine`, `TestSMTTurnedOnGivesTheMachinesCoresOfTheirOwn`, `TestAHostThatNoLongerKeepsItsMachinesApartIsDrained`; the VM lane's `TestAMachinesQEMUReachesNothingOnTheHostOrAnotherMachine`, `TestAGuestAnswersOnlyTheRunner`, `TestAMachineIsBornWithinItsBounds`; `TestAMachineWithAUserOfItsOwnIsLaunchedApart`, `TestARunnersMachineMergesNoPagesAcrossMachines` | | I15 | A program that parses a tenant's bytes on the host opens only the files of its operation. | `TestOnlyARootRunnerOnANewLandlockSaysItHoldsAProgramToItsFiles`, `TestAProductionInstallationPlacesOnlyOnIsolatedHosts`, `TestQemuImgDoesItsWorkWithOnlyItsFiles`, `TestAProgramReadsOnlyWhatItIsGiven`, `TestAProgramWritesOnlyWhatItIsGiven`, `TestAProgramMakesNoSocket`; the VM lane's `TestARootRunnersProgramHoldsNothingOfRoots`; the storage fakes refuse a file a run was not given, as the kernel does | | I16 | A store on the control plane's machine is reached by the installation's administrators only through the control plane, and by its processes only for what each is. | `TestOnlyTheControlPlaneSaysWhoTheAdministratorIs`, `TestGrafanaShowsTheStoreToTheAdministratorItIsTold`, `TestNothingWithoutTheStoresKeyTakesItsMetrics`, `TestTheStoresRunWhileTheirControlPlaneDoes` (each account to each port, against the kernel), `TestTheStoresGuardNamesEveryPortAndOnlyAccountsTheImageHas`; the dashboard lane's `Monitoring access` and `Admin Metrics` | -| I17 | Only the keys of the people a workspace's access names - its owner and the guests they invited - log in to it, each with the installation's certificate over it, or a session key under a grant one of those keys signed, within its 12 h; the control plane holds no key that logs in and is never an SSH client of a guest (ADR-0030). | the sshd lanes' `TestSSHDLetsInOnlyACertificateOverAKeyTheHostAdmits`, `TestThePasskeyTerminalLogsInToTheClaimedGuest`; `TestAPreparedRootLetsInOnlyByItsHostsWord`, `TestALoginIsWhatTheHostSaysOfTheKey`, `TestALoginIsWhatTheNewestAccessSaysOfTheKey`, `TestAWordAdmitsTheKeysOfThePeopleItNames`, `TestTheNewestKeptWordIsTheHighestItsOwnerSigns`, `TestAMachineIsGivenItsOwnWorkspacesNewestAccess`, `TestTheControlPlaneKeepsOnlyTheOwnersNewerAccess`, `TestAGuestIsLetInByTheAccessThatNamesThem`, `TestATunnelCertifiesOnlyAKeyOfSomebodyTheAccessNames`, `TestOnlyTheListedProceduresAdmitAGuest`, `TestAKeyringStartedAnewIsAnotherChain`; `TestAGrantHoldsFromItsIssueToItsEnd`, `TestASessionKeyLogsInWhereTheKeyThatGrantedItWould`, `TestASessionKeySignsOnlyAFirstAccessThatLetsInItsOwner`, `TestASessionKeysFirstWrittenAfterTheOwnersIsPassedOver`, `TestATunnelCertifiesASessionKeyOnlyUnderAGrantThatHolds`, `TestALoginUnderAGrantIsThePersonsWhoseKeySignedIt`, `TestSSHDHandsTheHostTheGrantACertificateCarries`; the VM lane's `TestOnlyThePeopleTheAccessNamesLogInToAWorkspace`, `TestAGuestTakenOutStaysOutOfAWorkspaceRestoredToBeforeIt`, `TestTheOwnerLogsInToACloneOfTheirOwnSnapshot`; `TestAGuestIsConnectedToOnlyByAClaimThatHolds`, `TestASessionIsRefusedBeforeTheRelayIsDialled` | -| I19 | A workspace's identity is signed by the host that runs it, for the machine that asked, named only as its owner's access says - its team, owner, image and parent, fixed by the first - held to the owner's keyring and the team's roster, which people sign, and given only for an audience the access names; the control plane holds no key that signs one (ADR-0030). | `TestATokenIsTheAskingMachinesWorkspace`, `TestATokenIsForAnAudienceItsOwnerNamed`, `TestAWordGivesTheIdentityForTheAudiencesItNames`, `TestARunIsHeldToTheFirstKeyItPresents`, `TestAMachineIsNamedAsItsAccessSays`, `TestAnOwnerWhoseKeyringStartedAnewNamesNoMachine`, `TestABookSaysWhoIsAMemberByTheKeyringTheRosterNames`, `TestAKeyringIsAChainItsOwnKeysSigned`, `TestARosterIsAChainItsOwnersSigned`, `TestOnlyATeamOfOneStartsAnew`, `TestASignatureIsKeptOnlyAsProposedByWhoMaySignIt`, `TestAKeyringStartsAnewWhenItsPersonAsks`, `TestATeamOfMoreThanOneIsSignedAgainByAnotherOwner`, `TestAHostOpensTheKeyThroughAnAttestedDecrypt`, `TestAHostWritesOnlyItsOwnIdentityRecords`; the VM lane's `TestAWorkspacesIdentityIsTheHostsSignatureOfWhatItsOwnerSigned` | -| I18 | What a workspace applies of its owner's settings, what of it leaves it, and which egress root it trusts are its access's: settings only as approved by their digest, the journal and the console only with consent, the root only as named by its digest (ADR-0030). | `TestOnlySettingsTheOwnerApprovedAreApplied`, `TestTheJournalIsSentOnlyWithTheOwnersConsent`, `TestTheEgressRootIsTrustedOnlyByTheOwnersWord`, `TestAWordNamesOnlyTheEgressRootThisMachinePinned`, `TestTheConsoleLeavesTheHostOnlyAsTheNewestAccessSays`, `TestAConsoleLeavesTheHostOnlyWithItsOwnersConsent` | +| I17 | Only the keys of the people a workspace's access names - its owner and the guests they invited - log in to it, each with the installation's certificate over it, or a session key under a grant one of those keys signed, within its 7 days; the control plane holds no key that logs in and is never an SSH client of a guest (ADR-0030). | the sshd lanes' `TestSSHDLetsInOnlyACertificateOverAKeyTheHostAdmits`, `TestThePasskeyTerminalLogsInToTheClaimedGuest`; `TestAPreparedRootLetsInOnlyByItsHostsWord`, `TestALoginIsWhatTheHostSaysOfTheKey`, `TestALoginIsWhatTheNewestAccessSaysOfTheKey`, `TestAWordAdmitsTheKeysOfThePeopleItNames`, `TestTheNewestKeptWordIsTheHighestItsOwnerSigns`, `TestAMachineIsGivenItsOwnWorkspacesNewestAccess`, `TestTheControlPlaneKeepsOnlyTheOwnersNewerAccess`, `TestAGuestIsLetInByTheAccessThatNamesThem`, `TestATunnelCertifiesOnlyAKeyOfSomebodyTheAccessNames`, `TestOnlyTheListedProceduresAdmitAGuest`, `TestAKeyringStartedAnewIsAnotherChain`; `TestAGrantHoldsFromItsIssueToItsEnd`, `TestASessionKeyLogsInWhereTheKeyThatGrantedItWould`, `TestASessionKeySignsOnlyAFirstAccessThatLetsInItsOwner`, `TestASessionKeysFirstWrittenAfterTheOwnersIsPassedOver`, `TestATunnelCertifiesASessionKeyOnlyUnderAGrantThatHolds`, `TestALoginUnderAGrantIsThePersonsWhoseKeySignedIt`, `TestSSHDHandsTheHostTheGrantACertificateCarries`, `TestOnePromptSignsASetAndOnlyWhatItLists`, `TestASetsNamespaceIsTheSetsAlone`; the VM lane's `TestOnlyThePeopleTheAccessNamesLogInToAWorkspace`, `TestAGuestTakenOutStaysOutOfAWorkspaceRestoredToBeforeIt`, `TestTheOwnerLogsInToACloneOfTheirOwnSnapshot`; `TestAGuestIsConnectedToOnlyByAClaimThatHolds`, `TestASessionIsRefusedBeforeTheRelayIsDialled` | +| I19 | A workspace's identity is signed by the host that runs it, for the machine that asked, named only as its owner's access says - its team, owner, image and parent, fixed by the first - held to the owner's keyring and the team's roster, which people sign, and given only for an audience the installation allows; the control plane holds no key that signs one (ADR-0030). | `TestATokenIsTheAskingMachinesWorkspace`, `TestATokenIsForAnAudienceTheInstallationAllows`, `TestARunIsHeldToTheFirstKeyItPresents`, `TestAMachineIsNamedAsItsAccessSays`, `TestAnOwnerWhoseKeyringStartedAnewNamesNoMachine`, `TestABookSaysWhoIsAMemberByTheKeyringTheRosterNames`, `TestAKeyringIsAChainItsOwnKeysSigned`, `TestARosterIsAChainItsOwnersSigned`, `TestOnlyATeamOfOneStartsAnew`, `TestASignatureIsKeptOnlyAsProposedByWhoMaySignIt`, `TestAKeyringStartsAnewWhenItsPersonAsks`, `TestATeamOfMoreThanOneIsSignedAgainByAnotherOwner`, `TestAHostOpensTheKeyThroughAnAttestedDecrypt`, `TestAHostWritesOnlyItsOwnIdentityRecords`; the VM lane's `TestAWorkspacesIdentityIsTheHostsSignatureOfWhatItsOwnerSigned` | +| I18 | What a workspace applies of its owner's - dotfiles, shell, environment, editor settings, Taskfile, the workspace's own environment, and the repository it clones - is what a key of the owner's newest keyring signed; a session key signs none of it, so an account taken over changes settings that apply nowhere. A repository is cloned only at a URL and ref they named, a pull request's head only where they named its ref too, a commit only in the history of the ref they named, and a disk's checkout from a prebuild only as the claim its building host signed says it is - that repository at the commit the guest is told. A guest is given what of the settings is its own workspace's, never another's environment, and the owner's own settings - all but the repository - only where they alone are root: not with a guest let in, nor on a copy of another person's snapshot. A control plane, which can open a root shell on any host, can hand back settings the owner signed before. | `TestTheHostApprovesOnlySettingsTheOwnersKeyringSigned`, `TestAPullRequestIsFetchedOnlyWhereTheSettingsNameIt`, `TestAGuestIsGivenItsOwnWorkspacesSettingsAlone`, `TestTheOwnersSettingsAreWithheldWhereOthersAreRoot`, `TestADisksCheckoutIsHeldToItsPrebuildsClaim`, `TestAPrebuildsBuildIsApprovedItsOwnCheckoutAlone`, `TestABuildChecksOutItsCommit`, `TestAPrebuildsCheckoutIsHeldToItsCommit`, `TestTheHostHoldsTheSettingsItsNewestSetCarries`, `TestOnlySettingsTheOwnerSignedAreApplied`, `TestSettingsHandedToARunningGuestApplyAsTheyCome`, `TestSettingsTheHostHasNotYetAreAskedForAgain`, `TestAProjectsRepositoryIsClonedAndItsTasksRunOnceApproved`, `TestAPersonsSettingsAreKeptOnlySignedByTheirKeyring`, `TestSettingsAreWhatTheKeyThatSignedThemSigned`, `TestADescriptionWritesOutWhatWouldNotShow`, `TestSettingsThatHideWhatTheyRunAreNotSigned`, `TestSettingsThatHideWhatTheyRunAreNotSaved`, `TestTheOwnersSettingsGoOnceAGuestIsLetIn`, `TestSettingsToSignAreShownAgainstThoseSignedLast`, `TestAProjectOpensFromItsNewestPrebuild`; the e2e lane's `TestSettingsChangedWithoutThePersonsKeyApplyNowhere` | | I20 | No commit holds a credential, in any file. | `task lint:secrets` | | I21 | A team's secret kept as a reference is read only as the team whose secret it is, so a team's admin cannot name another team's secret, or the installation's. | `TestASecretIsReadInASessionTaggedWithItsTeam`, `TestASecretSetAsAReferenceIsReadAsTheTeamBeforeItIsKept`, `TestASecretKeptAsAReferenceIsReadAsTheTeamThatKeepsIt`; spin-terraform-aws's posture run `a_teams_secret_is_read_only_as_the_team` | | I22 | A header the egress proxy sets for a workspace goes on no request its rule's scope - methods, a path prefix by whole segments - leaves out. | `TestAnInjectionIsSetOnlyOnTheRequestsItsScopeNames`, `TestARequestOutsideAnInjectionsScopeIsRefused`, `TestAnInjectionCrossesTheWireWhole` | +| I23 | A span a client sends the installation is kept as the client and the person whose credential sent it, never as anyone or anything else. | `TestAnExportReachesTheCollectorAsWhoSentIt`, `TestAnExportTheProxyCannotStampReachesNoCollector`, `TestExportsPastTheBoundAreToldToSendAgain`, `TestAnExportsSenderIsTheUserAuthFound`; the CLI lane's `TestE2E_ACommandIsASpanOfTheTraceItIsHanded` | diff --git a/src/content/docs/reference/status/index.md b/src/content/docs/reference/status/index.md index a76be1e..61a3d25 100644 --- a/src/content/docs/reference/status/index.md +++ b/src/content/docs/reference/status/index.md @@ -9,7 +9,7 @@ sidebar: -Every row of this page is a line of `internal/features` in spin, and a test there resolves it against the tree. A row that says **built** names what shows the feature exists - a procedure the control plane serves, a command the CLI has, or a test - and, under **End to end**, the tests that drive a real runner and its guest and check what the feature did, or what no test checks yet. spin's build checks that each of those tests is there and not quarantined; whether it checks the whole feature is its review's. A row that says **not built** is an item of [`docs/ROADMAP.md`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/docs/ROADMAP.md). The page is written by `task reference` from `spin features` at spin `2cfbcd74d`, and cannot say a feature the binary does not. spin is a private repository: a link to its code opens only for someone with access to it. +Every row of this page is a line of `internal/features` in spin, and a test there resolves it against the tree. A row that says **built** names what shows the feature exists - a procedure the control plane serves, a command the CLI has, or a test - and, under **End to end**, the tests that drive a real runner and its guest and check what the feature did, or what no test checks yet. spin's build checks that each of those tests is there and not quarantined; whether it checks the whole feature is its review's. A row that says **not built** is an item of [`docs/ROADMAP.md`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/docs/ROADMAP.md). The page is written by `task reference` from `spin features` at spin `3cb9bb55f`, and cannot say a feature the binary does not. spin is a private repository: a link to its code opens only for someone with access to it. ## Built @@ -17,126 +17,126 @@ Every row of this page is a line of `internal/features` in spin, and a test ther | Feature | Exists | End to end | |---|---|---| -| A machine per workspace: KVM, its own kernel, root, a persistent disk, SSH | [`TestAWorkspaceBootsARealGuest`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/vm_test.go#L189), a test of `internal/e2e` | [`TestAWorkspaceBootsARealGuest`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/vm_test.go#L189) | -| Create, start, stop and delete | [`WorkspaceService/CreateWorkspace`](/reference/api/workspaceservice/) | [`TestE2E_WorkspaceCRUD`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/cmd/cli/e2e_test.go#L415) | -| A trash: a deleted workspace stays whole, for its owner to undelete, until its days are up | [`TestAWorkspaceWhoseDaysInTheTrashAreUpIsErasedFromItsHost`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/background_test.go#L379), a test of `internal/e2e` | [`TestATrashedWorkspaceIsWholeWhenItsOwnerUndeletesIt`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/background_test.go#L411)
[`TestAWorkspaceWhoseDaysInTheTrashAreUpIsErasedFromItsHost`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/background_test.go#L379) | -| Idle suspend, with a question before it that a keep answers | [`TestAWorkspaceIsAskedBeforeItsSuspensionAndAKeepAnswersIt`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/background_test.go#L107), a test of `internal/e2e` | [`TestAWorkspaceIsAskedBeforeItsSuspensionAndAKeepAnswersIt`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/background_test.go#L107) | -| A workspace that ran as long as the installation allows is suspended | [`TestAWorkspaceThatRanForAsLongAsAllowedIsSuspended`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/background_test.go#L69), a test of `internal/e2e` | [`TestAWorkspaceThatRanForAsLongAsAllowedIsSuspended`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/background_test.go#L69) | -| A process inside holds its workspace awake while it lives | [`TestAProcessHoldsItsWorkspaceAwakeWhileItLives`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/background_test.go#L190), a test of `internal/e2e` | [`TestAProcessHoldsItsWorkspaceAwakeWhileItLives`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/background_test.go#L190) | -| Suspend with the processes where they are; a start resumes them | [`TestAWorkspaceNobodyUsesIsSuspendedAndAStartResumesIt`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/background_test.go#L35), a test of `internal/e2e` | [`TestE2E_ASuspendedWorkspaceResumesWhereItWas`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/cmd/cli/journeys_e2e_test.go#L288)
[`TestAWorkspaceNobodyUsesIsSuspendedAndAStartResumesIt`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/background_test.go#L35) | -| Cores and memory lent while the host has them, and taken back
*A loan refused while the host is full has no test against the stack: the budget is the host's own cores and half its memory, which no lane's workspaces fill.* | [`TestABusyWorkspaceIsLentCoresAndGivesThemBack`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/background_test.go#L342), a test of `internal/e2e` | [`TestABusyWorkspaceIsLentCoresAndGivesThemBack`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/background_test.go#L342)
[`TestABusyWorkspaceIsLentMemoryAndGivesItBack`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/memory_test.go#L109) | -| A grant of cores and memory of its own, for a while | [`TestAGrantWhoseTimeIsUpIsGivenBackToTheMachine`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/background_test.go#L288), a test of `internal/e2e` | [`TestAGrantWhoseTimeIsUpIsGivenBackToTheMachine`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/background_test.go#L288)
[`TestAResumedWorkspaceIsGivenWhatItIsGrantedWhileItRuns`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/resume_grant_test.go#L20) | -| An administrator changes a running workspace's bandwidth, its connections open | [`TestAnAdministratorChangesARunningWorkspacesBandwidth`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/bandwidth_test.go#L118), a test of `internal/e2e` | [`TestAnAdministratorChangesARunningWorkspacesBandwidth`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/bandwidth_test.go#L118)
[`TestAWorkspacesBandwidthHoldsAcrossItsRunsAndItsRunner`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/bandwidth_test.go#L172) | -| Move a running workspace to another host, its processes as they are | [`TestHostsAMoveTakesARunningWorkspaceToAnotherHost`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/hosts_flows_test.go#L65), a test of `internal/e2e` | [`TestHostsAMoveTakesARunningWorkspaceToAnotherHost`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/hosts_flows_test.go#L65) | -| Clone a workspace: its disk, team, project, size, policies and environment, in one | [`TestACloneHoldsWhatItsSourceWroteAndItsShape`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/clone_test.go#L64), a test of `internal/e2e` | [`TestACloneHoldsWhatItsSourceWroteAndItsShape`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/clone_test.go#L64) | -| Recover a workspace whose host is gone, at a cost its owner accepts | [`TestHostsAWorkspaceWhoseHostIsGoneIsRecoveredOnAnother`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/hosts_flows_test.go#L100), a test of `internal/e2e` | [`TestHostsAWorkspaceWhoseHostIsGoneIsRecoveredOnAnother`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/hosts_flows_test.go#L100) | -| A workspace outlives its runner | [`TestAWorkspaceOutlivesItsRunner`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/vm_test.go#L272), a test of `internal/e2e` | [`TestAWorkspaceOutlivesItsRunner`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/vm_test.go#L272) | -| Quarantine, by an administrator | [`WorkspaceService/QuarantineWorkspace`](/reference/api/workspaceservice/) | [`TestE2E_AQuarantinedWorkspaceIsHeldUntilReleased`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/cmd/cli/journeys_e2e_test.go#L337) | -| Why a workspace is not behaving: status, console, history | [`spin workspace status`](/reference/cli/workspace/) | [`TestE2E_AQuarantinedWorkspaceIsHeldUntilReleased`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/cmd/cli/journeys_e2e_test.go#L337)
[`TestE2E_AWorkspacesConsoleIsWhatItsMachinePrinted`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/cmd/cli/journeys_e2e_test.go#L371) | -| The owner's shell, environment, editor settings, Taskfile and dotfiles reach the guest | [`TestAWorkspacesOwnEnvironmentIsInItsOwnersLoginShell`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/env_test.go#L23), a test of `internal/e2e` | [`TestTheOwnersSettingsArriveInTheGuest`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/env_test.go#L64)
[`TestAWorkspacesOwnEnvironmentIsInItsOwnersLoginShell`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/env_test.go#L23) | -| Reset a disk to what it was created from | [`spin workspace reset`](/reference/cli/workspace/) | [`TestE2E_ResetPutsAWorkspaceBackToWhatItWasCreatedFrom`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/cmd/cli/e2e_test.go#L1197) | -| Claude Code, Codex and T3 Code on every workspace's PATH, at the versions the release pins, with their own defaults
*Where the installation fetches them (agents_fetch) or an operator publishes them: no image carries Claude Code, which only Anthropic may distribute.* | [`TestTheAgentCLIsAreOnPathWithThePinnedVersions`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/agentclis_test.go#L20), a test of `internal/e2e` | [`TestTheAgentCLIsAreOnPathWithThePinnedVersions`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/agentclis_test.go#L20) | -| An agent UI: T3 Code in a workspace as its agent user, over the owner's SSH session - from `spin agent` on the person's computer, or in the workspace's Agent tab in the dashboard, which frames the terminal's agent page that carries the client over a passkey's session
*The lane has no provider credential, so no test has a model answer through the brokered egress: the server is reached, as the agent's user, and nothing is asked of it. The browser's test drives the page with a virtual authenticator, which no real passkey's maker vouches for.* | [`spin agent --port`](/reference/cli/agent/) | [`TestTheSupervisorRunsTheAgentForItsOwner`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/t3_test.go#L80)
[`TestE2E_TheAgentIsServedOnThisComputerWhileTheSessionIsOpen`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/cmd/cli/journeys_e2e_test.go#L94)
[`agent.spec.ts`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/dashboard/e2e/agent.spec.ts#L63): a passkey signs the person in, and the agent runs in their workspace from the terminal's page | -| Claude Code and Codex signed in from the agent's page: each CLI's own login, run by the supervisor as the agent's user, its credentials kept in the agent's home and never passing through the page
*The lane has no provider account: it begins a login and sees the provider's page, and finishing one is the unit tests' on each CLI's own output.* | `AgentService/BeginLogin` | [`TestTheSupervisorRunsTheAgentForItsOwner`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/t3_test.go#L80) | -| The supervisor runs the agent for its owner while it is used: started, paired and listed over the owner's own session on a socket only root opens, and stopped once nobody has used it for half an hour and no chat is at work
*That it stops once idle is the sweep's unit test on a clock the test moves: no lane waits half an hour.* | `AgentService/Start` | [`TestTheSupervisorRunsTheAgentForItsOwner`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/t3_test.go#L80) | -| The agent's chats listed on the workspace - titles, paths and times, never a message - reported by its supervisor only with the owner's consent | [`WorkspaceService/ListAgentThreads`](/reference/api/workspaceservice/) | [`TestTheAgentsThreadsAreListedOnlyWithTheOwnersConsent`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/t3_test.go#L136) | -| The agent's home is a volume of its own: the chats and sessions outlive the workspace, kept in the installation's store as every disk is, and a new workspace mounts them at its creation
*Sealed with the workspace's checkpoints, claimed with the launch beside the disk, and moved with the workspace.* | [`spin workspace create --agent-home`](/reference/cli/workspace/) | [`TestAnAgentsHomeOutlivesItsWorkspace`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/agenthome_test.go#L78) | +| A machine per workspace: KVM, its own kernel, root, a persistent disk, SSH | [`TestAWorkspaceBootsARealGuest`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/vm_test.go#L189), a test of `internal/e2e` | [`TestAWorkspaceBootsARealGuest`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/vm_test.go#L189) | +| Create, start, stop and delete | [`WorkspaceService/CreateWorkspace`](/reference/api/workspaceservice/) | [`TestE2E_WorkspaceCRUD`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/cmd/cli/e2e_test.go#L416) | +| A trash: a deleted workspace stays whole, for its owner to undelete, until its days are up | [`TestAWorkspaceWhoseDaysInTheTrashAreUpIsErasedFromItsHost`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/background_test.go#L379), a test of `internal/e2e` | [`TestATrashedWorkspaceIsWholeWhenItsOwnerUndeletesIt`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/background_test.go#L411)
[`TestAWorkspaceWhoseDaysInTheTrashAreUpIsErasedFromItsHost`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/background_test.go#L379) | +| Idle suspend, with a question before it that a keep answers | [`TestAWorkspaceIsAskedBeforeItsSuspensionAndAKeepAnswersIt`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/background_test.go#L107), a test of `internal/e2e` | [`TestAWorkspaceIsAskedBeforeItsSuspensionAndAKeepAnswersIt`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/background_test.go#L107) | +| A workspace that ran as long as the installation allows is suspended | [`TestAWorkspaceThatRanForAsLongAsAllowedIsSuspended`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/background_test.go#L69), a test of `internal/e2e` | [`TestAWorkspaceThatRanForAsLongAsAllowedIsSuspended`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/background_test.go#L69) | +| A process inside holds its workspace awake while it lives | [`TestAProcessHoldsItsWorkspaceAwakeWhileItLives`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/background_test.go#L190), a test of `internal/e2e` | [`TestAProcessHoldsItsWorkspaceAwakeWhileItLives`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/background_test.go#L190) | +| Suspend with the processes where they are; a start resumes them | [`TestAWorkspaceNobodyUsesIsSuspendedAndAStartResumesIt`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/background_test.go#L35), a test of `internal/e2e` | [`TestE2E_ASuspendedWorkspaceResumesWhereItWas`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/cmd/cli/journeys_e2e_test.go#L288)
[`TestAWorkspaceNobodyUsesIsSuspendedAndAStartResumesIt`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/background_test.go#L35) | +| Cores and memory lent while the host has them, and taken back
*A loan refused while the host is full has no test against the stack: the budget is the host's own cores and half its memory, which no lane's workspaces fill.* | [`TestABusyWorkspaceIsLentCoresAndGivesThemBack`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/background_test.go#L342), a test of `internal/e2e` | [`TestABusyWorkspaceIsLentCoresAndGivesThemBack`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/background_test.go#L342)
[`TestABusyWorkspaceIsLentMemoryAndGivesItBack`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/memory_test.go#L109) | +| A grant of cores and memory of its own, for a while | [`TestAGrantWhoseTimeIsUpIsGivenBackToTheMachine`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/background_test.go#L288), a test of `internal/e2e` | [`TestAGrantWhoseTimeIsUpIsGivenBackToTheMachine`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/background_test.go#L288)
[`TestAResumedWorkspaceIsGivenWhatItIsGrantedWhileItRuns`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/resume_grant_test.go#L20) | +| An administrator changes a running workspace's bandwidth, its connections open | [`TestAnAdministratorChangesARunningWorkspacesBandwidth`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/bandwidth_test.go#L118), a test of `internal/e2e` | [`TestAnAdministratorChangesARunningWorkspacesBandwidth`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/bandwidth_test.go#L118)
[`TestAWorkspacesBandwidthHoldsAcrossItsRunsAndItsRunner`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/bandwidth_test.go#L172) | +| Move a running workspace to another host, its processes as they are | [`TestHostsAMoveTakesARunningWorkspaceToAnotherHost`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/hosts_flows_test.go#L65), a test of `internal/e2e` | [`TestHostsAMoveTakesARunningWorkspaceToAnotherHost`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/hosts_flows_test.go#L65) | +| Clone a workspace: its disk, team, project, size, policies and environment, in one | [`TestACloneHoldsWhatItsSourceWroteAndItsShape`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/clone_test.go#L64), a test of `internal/e2e` | [`TestACloneHoldsWhatItsSourceWroteAndItsShape`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/clone_test.go#L64) | +| Recover a workspace whose host is gone, at a cost its owner accepts | [`TestHostsAWorkspaceWhoseHostIsGoneIsRecoveredOnAnother`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/hosts_flows_test.go#L100), a test of `internal/e2e` | [`TestHostsAWorkspaceWhoseHostIsGoneIsRecoveredOnAnother`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/hosts_flows_test.go#L100) | +| A workspace outlives its runner | [`TestAWorkspaceOutlivesItsRunner`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/vm_test.go#L272), a test of `internal/e2e` | [`TestAWorkspaceOutlivesItsRunner`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/vm_test.go#L272) | +| Quarantine, by an administrator | [`WorkspaceService/QuarantineWorkspace`](/reference/api/workspaceservice/) | [`TestE2E_AQuarantinedWorkspaceIsHeldUntilReleased`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/cmd/cli/journeys_e2e_test.go#L337) | +| Why a workspace is not behaving: status, console, history | [`spin workspace status`](/reference/cli/workspace/) | [`TestE2E_AQuarantinedWorkspaceIsHeldUntilReleased`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/cmd/cli/journeys_e2e_test.go#L337)
[`TestE2E_AWorkspacesConsoleIsWhatItsMachinePrinted`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/cmd/cli/journeys_e2e_test.go#L370) | +| The owner's shell, environment, editor settings, Taskfile and dotfiles reach the guest once they sign them, and a change nobody signed reaches none | [`TestAWorkspacesOwnEnvironmentIsInItsOwnersLoginShell`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/env_test.go#L23), a test of `internal/e2e` | [`TestTheOwnersSettingsArriveInTheGuest`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/env_test.go#L82)
[`TestAWorkspacesOwnEnvironmentIsInItsOwnersLoginShell`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/env_test.go#L23)
[`TestSettingsChangedWithoutThePersonsKeyApplyNowhere`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/env_test.go#L128) | +| Reset a disk to what it was created from | [`spin workspace reset`](/reference/cli/workspace/) | [`TestE2E_ResetPutsAWorkspaceBackToWhatItWasCreatedFrom`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/cmd/cli/e2e_test.go#L1218) | +| Claude Code, Codex and T3 Code on every workspace's PATH, at the versions the release pins, with their own defaults
*Where the installation fetches them (agents_fetch) or an operator publishes them: no image carries Claude Code, which only Anthropic may distribute.* | [`TestTheAgentCLIsAreOnPathWithThePinnedVersions`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/agentclis_test.go#L20), a test of `internal/e2e` | [`TestTheAgentCLIsAreOnPathWithThePinnedVersions`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/agentclis_test.go#L20) | +| An agent UI: T3 Code in a workspace as its agent user, over the owner's SSH session - from `spin agent` on the person's computer, or in the workspace's Agent tab in the dashboard, which frames the terminal's agent page that carries the client over a passkey's session
*The lane has no provider credential, so no test has a model answer through the brokered egress: the server is reached, as the agent's user, and nothing is asked of it. The browser's test drives the page with a virtual authenticator, which no real passkey's maker vouches for.* | [`spin agent --port`](/reference/cli/agent/) | [`TestTheSupervisorRunsTheAgentForItsOwner`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/t3_test.go#L79)
[`TestE2E_TheAgentIsServedOnThisComputerWhileTheSessionIsOpen`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/cmd/cli/journeys_e2e_test.go#L94)
[`agent.spec.ts`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/dashboard/e2e/agent.spec.ts#L63): a passkey signs the person in, and the agent runs in their workspace from the terminal's page | +| Claude Code and Codex signed in from the agent's page: each CLI's own login, run by the supervisor as the agent's user, its credentials kept in the agent's home and never passing through the page
*The lane has no provider account: it begins a login and sees the provider's page, and finishing one is the unit tests' on each CLI's own output.* | `AgentService/BeginLogin` | [`TestTheSupervisorRunsTheAgentForItsOwner`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/t3_test.go#L79) | +| A person signs Claude Code and Codex in once: every workspace of theirs, plain or a project's, is handed the same credentials and hands back each refresh and logout, and a workspace that names a guest holds none
*The lane has no provider account: its login is the file the CLI writes, written as the agent's user. Only a workspace its owner's alone through all it came from holds them: a project opened from its prebuild does, but not a prebuild's build, a copy of another person's snapshot, or one made before the release that keeps the mark.* | [`TestAPersonSignsInToTheAgentOnceForEveryWorkspaceOfTheirs`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/agentcredentials_test.go#L32), a test of `internal/e2e` | [`TestAPersonSignsInToTheAgentOnceForEveryWorkspaceOfTheirs`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/agentcredentials_test.go#L32) | +| The supervisor runs the agent for its owner while it is used: started, paired and listed over the owner's own session on a socket only root opens, and stopped once nobody has used it for half an hour and no chat is at work
*That it stops once idle is the sweep's unit test on a clock the test moves: no lane waits half an hour.* | `AgentService/Start` | [`TestTheSupervisorRunsTheAgentForItsOwner`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/t3_test.go#L79) | +| The agent's chats listed on the workspace - titles, paths and times, never a message - reported by its supervisor | [`WorkspaceService/ListAgentThreads`](/reference/api/workspaceservice/) | [`TestTheAgentsThreadsAreListed`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/t3_test.go#L184) | +| The agent's home is a volume of its own: the chats and sessions outlive the workspace, kept in the installation's store as every disk is, and a new workspace mounts them at its creation
*Sealed with the workspace's checkpoints, claimed with the launch beside the disk, and moved with the workspace.* | [`spin workspace create --agent-home`](/reference/cli/workspace/) | [`TestAnAgentsHomeOutlivesItsWorkspace`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/agenthome_test.go#L78) | ### Teams and projects | Feature | Exists | End to end | |---|---|---| -| Open a repository, branch, commit or pull request from its URL, in the dashboard (/launch) and from the terminal
*From the terminal; the dashboard's /launch page makes the same create and has no test of its own against the stack.* | [`spin open --no-connect`](/reference/cli/open/) | [`TestE2E_AURLOpensTheWorkspaceItNames`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/cmd/cli/journeys_e2e_test.go#L222) | -| A workspace opened at a commit or a pull request, checked out as pr-<n> | [`TestAProjectsWorkspaceOpensAtTheCommitItWasAskedFor`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/project_test.go#L91), a test of `internal/e2e` | [`TestAProjectsWorkspaceOpensAtTheCommitItWasAskedFor`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/project_test.go#L91)
[`TestE2E_AURLOpensTheWorkspaceItNames`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/cmd/cli/journeys_e2e_test.go#L222) | -| Teams, with owner, admin and member | [`spin team member role`](/reference/cli/team/) | [`TestE2E_ATeamRoleIsWhatItsHolderMayDo`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/cmd/cli/e2e_test.go#L491) | -| A team's own identity providers | [`TeamService/CreateIdentityProvider`](/reference/api/teamservice/) | [`TestE2E_ATeamsIdentityProviderIsItsAdminsAndSignsNobodyIn`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/cmd/cli/e2e_test.go#L523) | +| Open a repository, branch, commit or pull request from its URL, in the dashboard (/launch) and from the terminal
*From the terminal; the dashboard's /launch page makes the same create and has no test of its own against the stack.* | [`spin open --no-connect`](/reference/cli/open/) | [`TestE2E_AURLOpensTheWorkspaceItNames`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/cmd/cli/journeys_e2e_test.go#L222) | +| A workspace opened at a commit or a pull request, checked out as pr-<n> | [`TestAProjectsWorkspaceOpensAtTheCommitItWasAskedFor`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/project_test.go#L90), a test of `internal/e2e` | [`TestAProjectsWorkspaceOpensAtTheCommitItWasAskedFor`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/project_test.go#L90)
[`TestE2E_AURLOpensTheWorkspaceItNames`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/cmd/cli/journeys_e2e_test.go#L222) | +| Teams, with owner, admin and member | [`spin team member role`](/reference/cli/team/) | [`TestE2E_ATeamRoleIsWhatItsHolderMayDo`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/cmd/cli/e2e_test.go#L492) | +| A team's own identity providers | [`TeamService/CreateIdentityProvider`](/reference/api/teamservice/) | [`TestE2E_ATeamsIdentityProviderIsItsAdminsAndSignsNobodyIn`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/cmd/cli/e2e_test.go#L524) | | Your GitHub account, connected once: private repositories cloned and pushed with nothing on the disk | [`ForgeService/CompleteConnect`](/reference/api/forgeservice/) | not yet: consent takes a person on GitHub's page, and revoking a grant would end the one authorization a lane could live on: checked by hand once per release | | Your GitHub account connected from the CLI, with a code entered on GitHub's page | [`spin git connect`](/reference/cli/git/) | not yet: the code is entered by a person on GitHub's page: checked by hand once per release | | A repository picked from the ones your account reaches | [`spin git repos`](/reference/cli/git/) | not yet: a real GitHub account the lane can search with | -| A team's own network policies, where the installation allows them | [`spin team policy set`](/reference/cli/team/) | [`TestATeamsOwnPolicyIsWhatItsWorkspacesReach`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/team_policy_test.go#L24) | -| Projects of the installation: a repository and the shape of the workspace that opens it, shared with everyone or some | [`TestAProjectsWorkspaceHasItsRepositoryCheckedOutAtTheRef`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/project_test.go#L27), a test of `internal/e2e` | [`TestAProjectsWorkspaceHasItsRepositoryCheckedOutAtTheRef`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/project_test.go#L27) | -| Prebuilds of a project's refs, as the floor of the workspaces that open them | [`TestAProjectOpensAsItsPrebuildMadeIt`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/prebuild_test.go#L29), a test of `internal/e2e` | [`TestAProjectOpensAsItsPrebuildMadeIt`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/prebuild_test.go#L29) | -| A team's workspaces run on the installation's hosts | [`TestATeamsWorkspaceRunsOnTheInstallationsHost`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/team_test.go#L20), a test of `internal/e2e` | [`TestATeamsWorkspaceRunsOnTheInstallationsHost`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/team_test.go#L20) | +| A team's own network policies, where the installation allows them | [`spin team policy set`](/reference/cli/team/) | [`TestATeamsOwnPolicyIsWhatItsWorkspacesReach`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/team_policy_test.go#L24) | +| Projects of the installation: a repository and the shape of the workspace that opens it, shared with everyone or some | [`TestAProjectsWorkspaceHasItsRepositoryCheckedOutAtTheRef`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/project_test.go#L29), a test of `internal/e2e` | [`TestAProjectsWorkspaceHasItsRepositoryCheckedOutAtTheRef`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/project_test.go#L29) | +| Prebuilds of a project's refs, as the floor of the workspaces that open them | [`TestAProjectOpensAsItsPrebuildMadeIt`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/prebuild_test.go#L25), a test of `internal/e2e` | [`TestAProjectOpensAsItsPrebuildMadeIt`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/prebuild_test.go#L25) | +| A team's workspaces run on the installation's hosts | [`TestATeamsWorkspaceRunsOnTheInstallationsHost`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/team_test.go#L20), a test of `internal/e2e` | [`TestATeamsWorkspaceRunsOnTheInstallationsHost`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/team_test.go#L20) | ### Snapshots | Feature | Exists | End to end | |---|---|---| -| Snapshots of a running workspace's disk | [`WorkspaceService/CreateSnapshot`](/reference/api/workspaceservice/) | [`TestACloneHoldsWhatItsSourceWroteAndItsShape`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/clone_test.go#L64)
[`TestADiskSnapshottedPastTheThresholdIsCompactedWhileItRuns`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/compaction_test.go#L19) | -| Snapshots with memory, resumed with their processes | [`TestARunningWorkspaceResumesFromASnapshotsMemory`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/restore_test.go#L175), a test of `internal/e2e` | [`TestARunningWorkspaceResumesFromASnapshotsMemory`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/restore_test.go#L175) | -| Restore a workspace to a snapshot | [`TestARestoredWorkspaceBootsOnTheSnapshotItWasRestoredTo`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/restore_test.go#L29), a test of `internal/e2e` | [`TestARestoredWorkspaceBootsOnTheSnapshotItWasRestoredTo`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/restore_test.go#L29)
[`TestE2E_TheQuickstartsDiffIsWhatTheSiteShows`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/cmd/cli/site_e2e_test.go#L24) | -| A diff of the files that changed between two snapshots | [`TestADiffOfTwoSnapshotsIsWhatChangedBetweenThem`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/diff_test.go#L28), a test of `internal/e2e` | [`TestADiffOfTwoSnapshotsNamesWhatWasAddedChangedAndRemoved`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/diff_test.go#L95)
[`TestE2E_TheQuickstartsDiffIsWhatTheSiteShows`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/cmd/cli/site_e2e_test.go#L24) | -| Share a snapshot with a person or make it public, and create a workspace from it | [`TestACloneOfASnapshotRegistersAsItself`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/clone_test.go#L24), a test of `internal/e2e` | [`TestASharedSnapshotIsCreatedFromByThePersonItIsSharedWith`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/share_test.go#L22) | -| What looks like a credential is found before a share, and the share refused unless acknowledged | [`ShareService/ShareSnapshot`](/reference/api/shareservice/) | [`TestE2E_ASharedSnapshotIsScannedForCredentials`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/cmd/cli/journeys_e2e_test.go#L171) | -| A long chain is compacted while the workspace runs | [`TestADiskSnapshottedPastTheThresholdIsCompactedWhileItRuns`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/compaction_test.go#L19), a test of `internal/e2e` | [`TestADiskSnapshottedPastTheThresholdIsCompactedWhileItRuns`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/compaction_test.go#L19) | +| Snapshots of a running workspace's disk | [`WorkspaceService/CreateSnapshot`](/reference/api/workspaceservice/) | [`TestACloneHoldsWhatItsSourceWroteAndItsShape`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/clone_test.go#L64)
[`TestADiskSnapshottedPastTheThresholdIsCompactedWhileItRuns`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/compaction_test.go#L19) | +| Snapshots with memory, resumed with their processes | [`TestARunningWorkspaceResumesFromASnapshotsMemory`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/restore_test.go#L175), a test of `internal/e2e` | [`TestARunningWorkspaceResumesFromASnapshotsMemory`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/restore_test.go#L175) | +| Restore a workspace to a snapshot | [`TestARestoredWorkspaceBootsOnTheSnapshotItWasRestoredTo`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/restore_test.go#L29), a test of `internal/e2e` | [`TestARestoredWorkspaceBootsOnTheSnapshotItWasRestoredTo`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/restore_test.go#L29)
[`TestE2E_TheQuickstartsDiffIsWhatTheSiteShows`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/cmd/cli/site_e2e_test.go#L24) | +| A diff of the files that changed between two snapshots | [`TestADiffOfTwoSnapshotsIsWhatChangedBetweenThem`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/diff_test.go#L28), a test of `internal/e2e` | [`TestADiffOfTwoSnapshotsNamesWhatWasAddedChangedAndRemoved`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/diff_test.go#L95)
[`TestE2E_TheQuickstartsDiffIsWhatTheSiteShows`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/cmd/cli/site_e2e_test.go#L24) | +| Share a snapshot with a person or make it public, and create a workspace from it | [`TestACloneOfASnapshotRegistersAsItself`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/clone_test.go#L24), a test of `internal/e2e` | [`TestASharedSnapshotIsCreatedFromByThePersonItIsSharedWith`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/share_test.go#L22) | +| What looks like a credential is found before a share, and the share refused unless acknowledged | [`ShareService/ShareSnapshot`](/reference/api/shareservice/) | [`TestE2E_ASharedSnapshotIsScannedForCredentials`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/cmd/cli/journeys_e2e_test.go#L171) | +| A long chain is compacted while the workspace runs | [`TestADiskSnapshottedPastTheThresholdIsCompactedWhileItRuns`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/compaction_test.go#L19), a test of `internal/e2e` | [`TestADiskSnapshottedPastTheThresholdIsCompactedWhileItRuns`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/compaction_test.go#L19) | ### Network | Feature | Exists | End to end | |---|---|---| -| Egress is closed by default; policies, by tag, name what a workspace may reach | [`TestAnOwnerMayOnlyChooseAPolicyTheInstallationDeclares`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/retag_test.go#L163), a test of `internal/e2e` | [`TestAWorkspaceNamedNoPolicyReachesNothing`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/retag_test.go#L71)
[`TestChangingAWorkspacesPoliciesReachesTheHostThatRunsIt`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/retag_test.go#L24) | -| A workspace's DNS goes upstream only for what its policy names, so a policy that closes egress closes the tunnel through names | [`TestAWorkspaceAsksItsResolverOnlyWhatItsPolicyNames`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/resolver_test.go#L76), a test of `internal/e2e` | [`TestAWorkspaceAsksItsResolverOnlyWhatItsPolicyNames`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/resolver_test.go#L76) | -| A policy changed reaches the host that runs the workspace | [`TestChangingAWorkspacesPoliciesReachesTheHostThatRunsIt`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/retag_test.go#L24), a test of `internal/e2e` | [`TestAnEditedPolicyChangesWhatARunningGuestReaches`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/retag_test.go#L100)
[`TestChangingAWorkspacesPoliciesReachesTheHostThatRunsIt`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/retag_test.go#L24) | -| Brokered names: the host's proxy stands in and adds what the workspace never holds - a team secret, a forge token, its identity, a cloud role
*The team secret's value is read at the origin; the forge token, identity and cloud role injections have no test against the stack.* | [`spin team secret set`](/reference/cli/team/) | [`TestAPersonsRuleAndAnAgentsOnOneNameEachArriveWithTheirOwnInjection`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/brokered_test.go#L100) | -| A workspace trusts the egress root only by its owner's word | [`TestAGuestTrustsTheEgressRootOnlyByItsOwnersWord`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/egress_root_test.go#L20), a test of `internal/e2e` | [`TestAGuestTrustsTheEgressRootOnlyByItsOwnersWord`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/egress_root_test.go#L20) | -| What a workspace reached, what it looked up and what it was refused | [`spin workspace egress`](/reference/cli/workspace/) | [`TestE2E_EgressIsAnsweredByTheHostTheWorkspaceRunsOn`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/cmd/cli/e2e_test.go#L784) | -| Each request to a brokered name as the proxy read it, served or refused and why; and whether each injection's secret is the team's to give | [`TestABrokeredRequestIsSeenAsTheProxyReadIt`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/brokered_test.go#L28), a test of `internal/e2e` | [`TestABrokeredRequestIsSeenAsTheProxyReadIt`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/brokered_test.go#L28) | -| The egress proxy is a process of its own, holding no key of the host's, started again by the runner when it ends | [`TestTheEgressProxyIsAProcessOfItsOwnThatTheRunnerStartsAgain`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/egress_process_test.go#L21), a test of `internal/e2e` | [`TestTheEgressProxyIsAProcessOfItsOwnThatTheRunnerStartsAgain`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/egress_process_test.go#L21) | -| A brokered rule names whose it is, the agent's or the person's: one policy says what each may reach and with what | [`TestABrokeredNameForTheAgentIsTheAgentsAlone`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/brokered_test.go#L72), a test of `internal/e2e` | [`TestAPersonsRuleAndAnAgentsOnOneNameEachArriveWithTheirOwnInjection`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/brokered_test.go#L100)
[`TestABrokeredNameForTheAgentIsTheAgentsAlone`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/brokered_test.go#L72) | -| A WebSocket to a brokered name: its handshake under the rule's headers and scope, then bytes each way
*The rule's header on the handshake is not read at the origin: the lane's WebSocket echo answers frames, not headers.* | [`TestAWebSocketToABrokeredNameIsCarriedAfterItsHandshake`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/brokered_test.go#L168), a test of `internal/e2e` | [`TestAWebSocketToABrokeredNameCarriesTheGuestsBytesAndRefusesAPathOutOfScope`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/brokered_test.go#L196)
[`TestAWebSocketToABrokeredNameIsCarriedAfterItsHandshake`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/brokered_test.go#L168) | -| HTTP/2 to a brokered name, the proxy's ALPN the real host's: a rule's headers set stream by stream, gRPC's trailers both ways
*gRPC's trailers are egressproxy's h2 test against an origin of its own; the lane has no gRPC origin to reach.* | [`TestHTTP2ToABrokeredNameIsTheRealHosts`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/brokered_test.go#L231), a test of `internal/e2e` | [`TestHTTP2ToABrokeredNameIsTheRealHosts`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/brokered_test.go#L231)
[`TestEachStreamOfAnHTTP2ConnectionToABrokeredNameCarriesTheRulesHeader`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/brokered_test.go#L251) | -| Watch where a workspace connects, into its logs | [`spin workspace watch`](/reference/cli/workspace/) | [`TestE2E_AWatchedWorkspacesConnectionsAreInItsLogs`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/cmd/cli/journeys_e2e_test.go#L392) | -| An agent the supervisor starts is marked, and reaches only brokered names | [`TestARealWorkspaceMarksTheAgentItsSupervisorStarts`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/seal_test.go#L21), a test of `internal/e2e` | [`TestAnAgentReachesOnlyBrokeredNames`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/brokered_test.go#L138)
[`TestARealWorkspaceMarksTheAgentItsSupervisorStarts`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/seal_test.go#L21) | -| Published ports at https://{port}-{workspace}.{domain}: private, whitelisted or public | [`spin port expose`](/reference/cli/port/) | [`TestAPublicPortIsReachedWithNoSessionAtAll`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/cmd/proxy/lane_test.go#L144)
[`workspace-sign-in.spec.ts`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/dashboard/e2e/workspace-sign-in.spec.ts#L31): a visitor signed in to the dashboard reaches their private port | +| Egress is closed by default; policies, by tag, name what a workspace may reach | [`TestAnOwnerMayOnlyChooseAPolicyTheInstallationDeclares`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/retag_test.go#L163), a test of `internal/e2e` | [`TestAWorkspaceNamedNoPolicyReachesNothing`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/retag_test.go#L71)
[`TestChangingAWorkspacesPoliciesReachesTheHostThatRunsIt`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/retag_test.go#L24) | +| A workspace's DNS goes upstream only for what its policy names, so a policy that closes egress closes the tunnel through names | [`TestAWorkspaceAsksItsResolverOnlyWhatItsPolicyNames`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/resolver_test.go#L76), a test of `internal/e2e` | [`TestAWorkspaceAsksItsResolverOnlyWhatItsPolicyNames`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/resolver_test.go#L76) | +| A policy changed reaches the host that runs the workspace | [`TestChangingAWorkspacesPoliciesReachesTheHostThatRunsIt`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/retag_test.go#L24), a test of `internal/e2e` | [`TestAnEditedPolicyChangesWhatARunningGuestReaches`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/retag_test.go#L100)
[`TestChangingAWorkspacesPoliciesReachesTheHostThatRunsIt`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/retag_test.go#L24) | +| Brokered names: the host's proxy stands in and adds what the workspace never holds - a team secret, a forge token, its identity, a cloud role
*The team secret's value is read at the origin; the forge token, identity and cloud role injections have no test against the stack.* | [`spin team secret set`](/reference/cli/team/) | [`TestAPersonsRuleAndAnAgentsOnOneNameEachArriveWithTheirOwnInjection`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/brokered_test.go#L100) | +| What a workspace reached, what it looked up and what it was refused | [`spin workspace egress`](/reference/cli/workspace/) | [`TestE2E_EgressIsAnsweredByTheHostTheWorkspaceRunsOn`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/cmd/cli/e2e_test.go#L838) | +| Each request to a brokered name as the proxy read it, served or refused and why; and whether each injection's secret is the team's to give | [`TestABrokeredRequestIsSeenAsTheProxyReadIt`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/brokered_test.go#L28), a test of `internal/e2e` | [`TestABrokeredRequestIsSeenAsTheProxyReadIt`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/brokered_test.go#L28) | +| The egress proxy is a process of its own, holding no key of the host's, started again by the runner when it ends | [`TestTheEgressProxyIsAProcessOfItsOwnThatTheRunnerStartsAgain`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/egress_process_test.go#L21), a test of `internal/e2e` | [`TestTheEgressProxyIsAProcessOfItsOwnThatTheRunnerStartsAgain`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/egress_process_test.go#L21) | +| A brokered rule names whose it is, the agent's or the person's: one policy says what each may reach and with what | [`TestABrokeredNameForTheAgentIsTheAgentsAlone`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/brokered_test.go#L72), a test of `internal/e2e` | [`TestAPersonsRuleAndAnAgentsOnOneNameEachArriveWithTheirOwnInjection`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/brokered_test.go#L100)
[`TestABrokeredNameForTheAgentIsTheAgentsAlone`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/brokered_test.go#L72) | +| A WebSocket to a brokered name: its handshake under the rule's headers and scope, then bytes each way
*The rule's header on the handshake is not read at the origin: the lane's WebSocket echo answers frames, not headers.* | [`TestAWebSocketToABrokeredNameIsCarriedAfterItsHandshake`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/brokered_test.go#L168), a test of `internal/e2e` | [`TestAWebSocketToABrokeredNameCarriesTheGuestsBytesAndRefusesAPathOutOfScope`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/brokered_test.go#L196)
[`TestAWebSocketToABrokeredNameIsCarriedAfterItsHandshake`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/brokered_test.go#L168) | +| HTTP/2 to a brokered name, the proxy's ALPN the real host's: a rule's headers set stream by stream, gRPC's trailers both ways
*gRPC's trailers are egressproxy's h2 test against an origin of its own; the lane has no gRPC origin to reach.* | [`TestHTTP2ToABrokeredNameIsTheRealHosts`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/brokered_test.go#L231), a test of `internal/e2e` | [`TestHTTP2ToABrokeredNameIsTheRealHosts`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/brokered_test.go#L231)
[`TestEachStreamOfAnHTTP2ConnectionToABrokeredNameCarriesTheRulesHeader`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/brokered_test.go#L251) | +| Watch where a workspace connects, into its logs | [`spin workspace watch`](/reference/cli/workspace/) | [`TestE2E_AWatchedWorkspacesConnectionsAreInItsLogs`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/cmd/cli/journeys_e2e_test.go#L388) | +| An agent the supervisor starts is marked, and reaches only brokered names | [`TestARealWorkspaceMarksTheAgentItsSupervisorStarts`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/seal_test.go#L21), a test of `internal/e2e` | [`TestAnAgentReachesOnlyBrokeredNames`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/brokered_test.go#L138)
[`TestARealWorkspaceMarksTheAgentItsSupervisorStarts`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/seal_test.go#L21) | +| Published ports at https://{port}-{workspace}.{domain}: private, whitelisted or public | [`spin port expose`](/reference/cli/port/) | [`TestAPublicPortIsReachedWithNoSessionAtAll`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/cmd/proxy/lane_test.go#L144)
[`workspace-sign-in.spec.ts`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/dashboard/e2e/workspace-sign-in.spec.ts#L31): a visitor signed in to the dashboard reaches their private port | ### Access | Feature | Exists | End to end | |---|---|---| | Sign in with GitHub or an OIDC provider | [`AuthService/StartLogin`](/reference/api/authservice/) | not yet: a GitHub provider: the sign-in through it and the verified email it gives | -| Device login for a terminal | [`AuthService/StartDeviceLogin`](/reference/api/authservice/) | [`TestE2E_Logout`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/cmd/cli/e2e_test.go#L1184)
[`auth.spec.ts`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/dashboard/e2e/auth.spec.ts#L19): the CLI's device page stands alone and keeps its code through a sign-in | -| API keys for scripts and agents | [`spin api-key create`](/reference/cli/api-key/) | [`TestE2E_APIKeyCRUD`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/cmd/cli/e2e_test.go#L1139) | -| SSH keys, and plain ssh to spin.<workspace> | [`spin ssh-config`](/reference/cli/ssh-config/) | [`TestE2E_SSHConfigCarriesSSHToAWorkspace`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/cmd/cli/e2e_test.go#L655) | -| Who logs in to a workspace is what its owner signed | [`TestOnlyThePeopleTheAccessNamesLogInToAWorkspace`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/login_test.go#L259), a test of `internal/e2e` | [`TestOnlyThePeopleTheAccessNamesLogInToAWorkspace`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/login_test.go#L259) | -| Guests of a workspace, invited by its owner | [`spin workspace guests`](/reference/cli/workspace/) | [`TestOnlyThePeopleTheAccessNamesLogInToAWorkspace`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/login_test.go#L259) | -| A workspace's identity, signed by its host, for the audiences its owner allows | [`TestAWorkspacesIdentityIsTheHostsSignatureOfWhatItsOwnerSigned`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/identity_test.go#L60), a test of `internal/e2e` | [`TestAWorkspacesIdentityIsTheHostsSignatureOfWhatItsOwnerSigned`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/identity_test.go#L60) | -| VS Code over SSH, with the server the installation publishes and nothing downloaded
*The server is Microsoft's, for Remote-SSH; spin code also opens an editor with Open Remote - SSH, which downloads its own. spin code itself is run by its unit tests only: it opens a desktop editor, which no lane has.* | [`TestAVSCodeServerOfAnotherCommitIsHandedToTheRunningMachine`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/vscodehotplug_test.go#L23), a test of `internal/e2e` | [`TestTheCarriedVSCodeServerRunsOfflineAndAnswersOverTheSSHTunnel`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/vscodeserver_test.go#L86)
[`TestAVSCodeServerOfAnotherCommitIsHandedToTheRunningMachine`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/vscodehotplug_test.go#L23) | -| Run a command in a workspace, copy files to and from it | [`spin exec`](/reference/cli/exec/) | [`TestE2E_ADetachedRunIsFollowedToItsEndAndFilesGoBothWays`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/cmd/cli/journeys_e2e_test.go#L306) | +| Device login for a terminal | [`AuthService/StartDeviceLogin`](/reference/api/authservice/) | [`TestE2E_Logout`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/cmd/cli/e2e_test.go#L1205)
[`auth.spec.ts`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/dashboard/e2e/auth.spec.ts#L19): the CLI's device page stands alone and keeps its code through a sign-in | +| API keys for scripts and agents | [`spin api-key create`](/reference/cli/api-key/) | [`TestE2E_APIKeyCRUD`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/cmd/cli/e2e_test.go#L1160) | +| SSH keys, and plain ssh to spin.<workspace> | [`spin ssh-config`](/reference/cli/ssh-config/) | [`TestE2E_SSHConfigCarriesSSHToAWorkspace`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/cmd/cli/e2e_test.go#L709) | +| Who logs in to a workspace is what its owner signed | [`TestOnlyThePeopleTheAccessNamesLogInToAWorkspace`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/login_test.go#L307), a test of `internal/e2e` | [`TestOnlyThePeopleTheAccessNamesLogInToAWorkspace`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/login_test.go#L307) | +| Guests of a workspace, invited by its owner | [`spin workspace guests`](/reference/cli/workspace/) | [`TestOnlyThePeopleTheAccessNamesLogInToAWorkspace`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/login_test.go#L307) | +| A workspace's identity, signed by its host, for the audiences its owner allows | [`TestAWorkspacesIdentityIsTheHostsSignatureOfWhatItsOwnerSigned`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/identity_test.go#L59), a test of `internal/e2e` | [`TestAWorkspacesIdentityIsTheHostsSignatureOfWhatItsOwnerSigned`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/identity_test.go#L59) | +| VS Code over SSH, with the server the installation publishes and nothing downloaded
*The server is Microsoft's, for Remote-SSH; spin code also opens an editor with Open Remote - SSH, which downloads its own. spin code itself is run by its unit tests only: it opens a desktop editor, which no lane has.* | [`TestAVSCodeServerOfAnotherCommitIsHandedToTheRunningMachine`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/vscodehotplug_test.go#L23), a test of `internal/e2e` | [`TestTheCarriedVSCodeServerRunsOfflineAndAnswersOverTheSSHTunnel`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/vscodeserver_test.go#L86)
[`TestAVSCodeServerOfAnotherCommitIsHandedToTheRunningMachine`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/vscodehotplug_test.go#L23) | +| Run a command in a workspace, copy files to and from it | [`spin exec`](/reference/cli/exec/) | [`TestE2E_ADetachedRunIsFollowedToItsEndAndFilesGoBothWays`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/cmd/cli/journeys_e2e_test.go#L306) | ### Administration | Feature | Exists | End to end | |---|---|---| -| Installation settings seeded from a file; a change in the file is a proposal to apply or dismiss | [`AdminService/DecideConfigChange`](/reference/api/adminservice/) | [`TestTheInstallationFileSeedsAndItsChangesAreAnAdministratorsToDecide`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/config_file_test.go#L92) | -| Resource presets | [`AdminService/CreateResourcePreset`](/reference/api/adminservice/) | [`admin.spec.ts`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/dashboard/e2e/admin.spec.ts#L424): an admin's preset sizes a person's workspace, and is gone once deleted | -| Registration: open, by allowlist, or closed | [`AdminService/SetRegistrationMode`](/reference/api/adminservice/) | [`admin.spec.ts`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/dashboard/e2e/admin.spec.ts#L218): closed, open and a domain on the allowlist decide who registers
[`admin.spec.ts`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/dashboard/e2e/admin.spec.ts#L148): the allowlist lets in who it names, and nobody else | -| An audit log | [`AdminService/ListAuditLog`](/reference/api/adminservice/) | [`TestE2E_AnAdministratorsActionIsAuditedWithItsActorAndTarget`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/cmd/cli/e2e_test.go#L598)
[`admin.spec.ts`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/dashboard/e2e/admin.spec.ts#L897): admin reads the log and can narrow it to one kind of event | -| The control plane's jobs, and running one now | [`spin admin jobs`](/reference/cli/admin/) | [`TestE2E_Admin`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/cmd/cli/e2e_test.go#L1044)
[`admin.spec.ts`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/dashboard/e2e/admin.spec.ts#L707): admin runs a job by hand and sees how it ended | +| Installation settings seeded from a file; a change in the file is a proposal to apply or dismiss | [`AdminService/DecideConfigChange`](/reference/api/adminservice/) | [`TestTheInstallationFileSeedsAndItsChangesAreAnAdministratorsToDecide`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/config_file_test.go#L92) | +| Resource presets | [`AdminService/CreateResourcePreset`](/reference/api/adminservice/) | [`admin.spec.ts`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/dashboard/e2e/admin.spec.ts#L424): an admin's preset sizes a person's workspace, and is gone once deleted | +| Registration: open, by allowlist, or closed | [`AdminService/SetRegistrationMode`](/reference/api/adminservice/) | [`admin.spec.ts`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/dashboard/e2e/admin.spec.ts#L218): closed, open and a domain on the allowlist decide who registers
[`admin.spec.ts`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/dashboard/e2e/admin.spec.ts#L148): the allowlist lets in who it names, and nobody else | +| An audit log | [`AdminService/ListAuditLog`](/reference/api/adminservice/) | [`TestE2E_AnAdministratorsActionIsAuditedWithItsActorAndTarget`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/cmd/cli/e2e_test.go#L599)
[`admin.spec.ts`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/dashboard/e2e/admin.spec.ts#L897): admin reads the log and can narrow it to one kind of event | +| The control plane's jobs, and running one now | [`spin admin jobs`](/reference/cli/admin/) | [`TestE2E_Admin`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/cmd/cli/e2e_test.go#L1063)
[`admin.spec.ts`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/dashboard/e2e/admin.spec.ts#L707): admin runs a job by hand and sees how it ended | | The month's bill, its forecast, and what each workspace cost | [`spin admin costs`](/reference/cli/admin/) | not yet: the cloud's real bill read: no lane has an AWS account, so the bill a test gives the reader stands in for it | -| The store: every volume, whose it is, and taking out what nothing needs | [`spin admin storage list`](/reference/cli/admin/) | [`TestAVolumeNothingNeedsIsTakenOutOfTheStore`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/orphan_test.go#L26) | -| Re-key a workspace's disk | [`spin admin volume rekey`](/reference/cli/admin/) | [`TestARekeyedDiskBootsWithWhatItHeldUnderANewKey`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/rekey_test.go#L24) | -| Runners: registration tokens, drain, activate, revoke, and a policy per host | [`spin admin runner drain`](/reference/cli/admin/) | [`TestARunnerRegisteredWithATokenTheAPIMadeIsRevokedByTheAdmin`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/runner_token_test.go#L99)
[`TestARegistrationTokenExpiredOrRevokedRegistersNothing`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/runner_token_test.go#L148) | +| The store: every volume, whose it is, and taking out what nothing needs | [`spin admin storage list`](/reference/cli/admin/) | [`TestAVolumeNothingNeedsIsTakenOutOfTheStore`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/orphan_test.go#L26) | +| Re-key a workspace's disk | [`spin admin volume rekey`](/reference/cli/admin/) | [`TestARekeyedDiskBootsWithWhatItHeldUnderANewKey`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/rekey_test.go#L24) | +| Runners: registration tokens, drain, activate, revoke, and a policy per host | [`spin admin runner drain`](/reference/cli/admin/) | [`TestARunnerRegisteredWithATokenTheAPIMadeIsRevokedByTheAdmin`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/runner_token_test.go#L99)
[`TestARegistrationTokenExpiredOrRevokedRegistersNothing`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/runner_token_test.go#L148) | | Runners start when a workspace waits for one and stop when nothing runs | [`HostService/GetFleet`](/reference/api/hostservice/) | not yet: an autoscaling group to start and stop: the one group is AWS's, and no lane has an account | -| A root shell on a runner, for a while and with a reason: the runner emptied first, every session recorded under Object Lock, the runner retired after | [`spin admin shell open`](/reference/cli/admin/) | [`TestHostsARootShellOnAHostIsRecordedAndItsHostRetired`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/hosts_test.go#L420) | -| A host that reboots brings its workspaces back | [`TestAHostRebootBringsItsWorkspacesBack`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/restart_test.go#L38), a test of `internal/e2e` | [`TestAHostRebootBringsItsWorkspacesBack`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/restart_test.go#L38) | -| A cloud's reclaim warning empties the host before the machine goes | [`TestACloudsReclaimWarningEmptiesTheHostBeforeAnySignal`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/preemption_test.go#L26), a test of `internal/e2e` | [`TestACloudsReclaimWarningEmptiesTheHostBeforeAnySignal`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/preemption_test.go#L26) | -| A writeback bound per host, measured on that host before it is taken | [`TestCustomWritebackValuesAreMeasuredOnTheRunner`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/writeback_test.go#L28), a test of `internal/e2e` | [`TestCustomWritebackValuesAreMeasuredOnTheRunner`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/writeback_test.go#L28) | -| What is running where: the control plane, each runner and its machine | [`spin admin versions`](/reference/cli/admin/) | [`TestE2E_Admin`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/cmd/cli/e2e_test.go#L1044) | +| A root shell on a runner, for a while and with a reason: the runner emptied first, every session recorded under Object Lock, the runner retired after | [`spin admin shell open`](/reference/cli/admin/) | [`TestHostsARootShellOnAHostIsRecordedAndItsHostRetired`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/hosts_test.go#L420) | +| A host that reboots brings its workspaces back | [`TestAHostRebootBringsItsWorkspacesBack`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/restart_test.go#L38), a test of `internal/e2e` | [`TestAHostRebootBringsItsWorkspacesBack`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/restart_test.go#L38) | +| A cloud's reclaim warning empties the host before the machine goes | [`TestACloudsReclaimWarningEmptiesTheHostBeforeAnySignal`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/preemption_test.go#L26), a test of `internal/e2e` | [`TestACloudsReclaimWarningEmptiesTheHostBeforeAnySignal`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/preemption_test.go#L26) | +| A writeback bound per host, measured on that host before it is taken | [`TestCustomWritebackValuesAreMeasuredOnTheRunner`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/writeback_test.go#L28), a test of `internal/e2e` | [`TestCustomWritebackValuesAreMeasuredOnTheRunner`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/writeback_test.go#L28) | +| What is running where: the control plane, each runner and its machine | [`spin admin versions`](/reference/cli/admin/) | [`TestE2E_Admin`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/cmd/cli/e2e_test.go#L1063) | ### Observability | Feature | Exists | End to end | |---|---|---| -| Platform logs, workspace logs and traces, searched in the product | [`LogService/SearchPlatformLogs`](/reference/api/logservice/) | [`TestAWorkspacesLinesAndTracesAreFoundBySearchingForIt`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/observe_test.go#L130)
[`TestE2E_TheInstallationsLogsAreSearchable`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/cmd/cli/e2e_test.go#L946) | -| Metrics, with Grafana on the control plane | [`AdminService/GetMonitoring`](/reference/api/adminservice/) | [`admin.spec.ts`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/dashboard/e2e/admin.spec.ts#L1159): a series of the lane's host is in the metric store, read through Grafana
[`admin.spec.ts`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/dashboard/e2e/admin.spec.ts#L1128): admin reads the installation's dashboards without leaving the page | -| A workspace's journal and console are collected only with its owner's consent | [`spin workspace logs-consent`](/reference/cli/workspace/) | [`TestE2E_AWorkspacesConsoleIsKeptAndSearchable`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/cmd/cli/e2e_test.go#L967) | +| Platform logs, workspace logs and traces, searched in the product | [`LogService/SearchPlatformLogs`](/reference/api/logservice/) | [`TestAWorkspacesLinesAndTracesAreFoundBySearchingForIt`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/observe_test.go#L130)
[`TestE2E_TheInstallationsLogsAreSearchable`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/cmd/cli/e2e_test.go#L1000) | +| Metrics, with Grafana on the control plane | [`AdminService/GetMonitoring`](/reference/api/adminservice/) | [`admin.spec.ts`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/dashboard/e2e/admin.spec.ts#L1159): a series of the lane's host is in the metric store, read through Grafana
[`admin.spec.ts`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/dashboard/e2e/admin.spec.ts#L1128): admin reads the installation's dashboards without leaving the page | +| A workspace's journal and console are collected as the installation's policy says | [`spin workspace logs`](/reference/cli/workspace/) | [`TestE2E_AWorkspacesConsoleIsKeptAndSearchable`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/cmd/cli/e2e_test.go#L1021) | ### Platform | Feature | Exists | End to end | |---|---|---| -| A smoke test of what an installation's API promises, with a workspace of its own | [`spin smoke`](/reference/cli/smoke/) | [`TestE2E_SmokePassesAndLeavesNothingBehind`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/cmd/cli/journeys_e2e_test.go#L442) | -| A host serves only the releases it carries
*A resume whose recorded release was collected since has no test against the stack.* | [`TestAMachineAdoptedWithoutItsReleasesIsSuspendedWithItsDisk`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/suspend_test.go#L126), a test of `internal/e2e` | [`TestAMachineAdoptedWithoutItsReleasesIsSuspendedWithItsDisk`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/suspend_test.go#L126)
[`TestAVSCodeServerOfAnotherCommitIsHandedToTheRunningMachine`](https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/internal/e2e/vscodehotplug_test.go#L23) | +| A smoke test of what an installation's API promises, with a workspace of its own | [`spin smoke`](/reference/cli/smoke/) | [`TestE2E_SmokePassesAndLeavesNothingBehind`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/cmd/cli/journeys_e2e_test.go#L437) | +| A host serves only the releases it carries
*A resume whose recorded release was collected since has no test against the stack.* | [`TestAMachineAdoptedWithoutItsReleasesIsSuspendedWithItsDisk`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/suspend_test.go#L126), a test of `internal/e2e` | [`TestAMachineAdoptedWithoutItsReleasesIsSuspendedWithItsDisk`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/suspend_test.go#L126)
[`TestAVSCodeServerOfAnotherCommitIsHandedToTheRunningMachine`](https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/internal/e2e/vscodehotplug_test.go#L23) | ## Partly there diff --git a/src/content/docs/use/dashboard.md b/src/content/docs/use/dashboard.md index 76ead5c..b835cc3 100644 --- a/src/content/docs/use/dashboard.md +++ b/src/content/docs/use/dashboard.md @@ -7,7 +7,7 @@ editUrl: false -The dashboard is at `https://app.`. These screenshots are of spin v20261104.01, taken by spin's dashboard suite on its end-to-end stack - real workspaces on a real runner - each by a test that first checks the screen shows what its title says. Everything here is also in the [CLI](/reference/cli/) and the [API](/reference/api/). +The dashboard is at `https://app.`. These screenshots are of spin v20261106.01, taken by spin's dashboard suite on its end-to-end stack - real workspaces on a real runner - each by a test that first checks the screen shows what its title says. Everything here is also in the [CLI](/reference/cli/) and the [API](/reference/api/). ## A person's workspaces diff --git a/src/data/features.json b/src/data/features.json index 0765840..557abc8 100644 --- a/src/data/features.json +++ b/src/data/features.json @@ -188,13 +188,14 @@ }, { "area": "Workspaces", - "name": "The owner's shell, environment, editor settings, Taskfile and dotfiles reach the guest", + "name": "The owner's shell, environment, editor settings, Taskfile and dotfiles reach the guest once they sign them, and a change nobody signed reaches none", "state": "built", "proof": "e2e:TestAWorkspacesOwnEnvironmentIsInItsOwnersLoginShell", "note": "", "endToEnd": [ "go:internal/e2e.TestTheOwnersSettingsArriveInTheGuest", - "go:internal/e2e.TestAWorkspacesOwnEnvironmentIsInItsOwnersLoginShell" + "go:internal/e2e.TestAWorkspacesOwnEnvironmentIsInItsOwnersLoginShell", + "go:internal/e2e.TestSettingsChangedWithoutThePersonsKeyApplyNowhere" ] }, { @@ -336,16 +337,6 @@ "go:internal/e2e.TestAPersonsRuleAndAnAgentsOnOneNameEachArriveWithTheirOwnInjection" ] }, - { - "area": "Network", - "name": "A workspace trusts the egress root only by its owner's word", - "state": "built", - "proof": "e2e:TestAGuestTrustsTheEgressRootOnlyByItsOwnersWord", - "note": "", - "endToEnd": [ - "go:internal/e2e.TestAGuestTrustsTheEgressRootOnlyByItsOwnersWord" - ] - }, { "area": "Network", "name": "What a workspace reached, what it looked up and what it was refused", @@ -553,6 +544,16 @@ "go:internal/e2e.TestTheSupervisorRunsTheAgentForItsOwner" ] }, + { + "area": "Workspaces", + "name": "A person signs Claude Code and Codex in once: every workspace of theirs, plain or a project's, is handed the same credentials and hands back each refresh and logout, and a workspace that names a guest holds none", + "state": "built", + "proof": "e2e:TestAPersonSignsInToTheAgentOnceForEveryWorkspaceOfTheirs", + "note": "The lane has no provider account: its login is the file the CLI writes, written as the agent's user. Only a workspace its owner's alone through all it came from holds them: a project opened from its prebuild does, but not a prebuild's build, a copy of another person's snapshot, or one made before the release that keeps the mark.", + "endToEnd": [ + "go:internal/e2e.TestAPersonSignsInToTheAgentOnceForEveryWorkspaceOfTheirs" + ] + }, { "area": "Workspaces", "name": "The supervisor runs the agent for its owner while it is used: started, paired and listed over the owner's own session on a socket only root opens, and stopped once nobody has used it for half an hour and no chat is at work", @@ -565,12 +566,12 @@ }, { "area": "Workspaces", - "name": "The agent's chats listed on the workspace - titles, paths and times, never a message - reported by its supervisor only with the owner's consent", + "name": "The agent's chats listed on the workspace - titles, paths and times, never a message - reported by its supervisor", "state": "built", "proof": "rpc:spin.v1.WorkspaceService/ListAgentThreads", "note": "", "endToEnd": [ - "go:internal/e2e.TestTheAgentsThreadsAreListedOnlyWithTheOwnersConsent" + "go:internal/e2e.TestTheAgentsThreadsAreListed" ] }, { @@ -858,9 +859,9 @@ }, { "area": "Observability", - "name": "A workspace's journal and console are collected only with its owner's consent", + "name": "A workspace's journal and console are collected as the installation's policy says", "state": "built", - "proof": "cli:workspace logs-consent", + "proof": "cli:workspace logs", "note": "", "endToEnd": [ "go:cmd/cli.TestE2E_AWorkspacesConsoleIsKeptAndSearchable" diff --git a/src/data/figures.json b/src/data/figures.json index 556382b..5d872e9 100644 --- a/src/data/figures.json +++ b/src/data/figures.json @@ -1,6 +1,6 @@ { "datapath": { - "source": "https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/docs/network/datapath", + "source": "https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/docs/network/datapath", "width": 552, "words": [ "How a packet leaves a workspace", @@ -56,8 +56,8 @@ ] }, "egress-policy": { - "source": "https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/docs/network/egress-policy", - "width": 854, + "source": "https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/docs/network/egress-policy", + "width": 923, "words": [ "What the forward chain decides, in order", "a packet from a machine", @@ -66,16 +66,30 @@ "10/8 · 172.16/12 · 192.168/16 · 127/8", "169.254/16 · 100.64/10 · 224/4 · 240/4", "+ every address the node answers on", + "1a · ip dscp \u003cagent's mark\u003e", + "an agent's packet: only the egress proxy", + "stands in for what it may reach", + "no", + "dropped, and counted", + "match", + "1b · oifname wan0 ct state established,related", + "what the machine already had open", + "no", + "match", + "1c · ip saddr @held", + "a machine taken back from the last runner,", + "until its record says what it carries", + "no", + "accepted - and recorded in @observed", + "machine . destination, with a counter, 6 h", + "match", "2 · ip saddr @tag_\u003cname\u003e ip daddr \u003callowed\u003e", "what a tag permits", "no", - "dropped, and counted", "match", "3 · ip saddr @tag_\u003cname\u003e", "and nothing else, when the tag says so", "no", - "accepted - and recorded in @observed", - "machine . destination, with a counter, 6 h", "match", "4 · oifname wan0", "the default: open beyond the node", @@ -104,6 +118,8 @@ "2 and 3 are between them, so a tag cannot open the node and a", "tag that closes a machine is reached by what its own rules did", "not claim.", + "1c is after 1b, so a runner's restart cuts nothing a machine", + "had open, and before 4, which a machine in no tag set reaches.", "4 is open on purpose. There is no allowlist to write yet, so", "the accept records where it went instead - see @observed, and", "`SIGUSR1` to the runner." @@ -157,7 +173,7 @@ ] }, "isolation": { - "source": "https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/docs/network/isolation", + "source": "https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/docs/network/isolation", "width": 499, "words": [ "Same address, different segment", @@ -204,7 +220,7 @@ ] }, "traffic": { - "source": "https://github.com/spin-stack/spin/blob/2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9/docs/security/traffic", + "source": "https://github.com/spin-stack/spin/blob/3cb9bb55ff21e9b9ff669480dc9053aa9dee732a/docs/security/traffic", "width": 1889, "words": [ "Traffic: every arrow is a connection opened in its direction, and nothing else is let in", diff --git a/src/data/pricing.json b/src/data/pricing.json index bff5065..9779afd 100644 --- a/src/data/pricing.json +++ b/src/data/pricing.json @@ -1,6 +1,6 @@ { - "generated": "2026-11-05", - "published": "2026-11-04T21:03:05Z", + "generated": "2026-11-06", + "published": "2026-11-05T16:26:28Z", "source": "https://b0.p.awsstatic.com/pricing/2.0/meteredUnitMaps/ec2/USD/current/ec2-ondemand-without-sec-sel/\u003cregion\u003e/Linux/index.json", "machines": { "controlPlane": "t8i.medium", diff --git a/src/data/reference.json b/src/data/reference.json index a05ba8e..2de5a05 100644 --- a/src/data/reference.json +++ b/src/data/reference.json @@ -1,8 +1,8 @@ { "spin": { "installs": "v20261027.01", - "commit": "2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9", - "tag": "v20261104.01", + "commit": "3cb9bb55ff21e9b9ff669480dc9053aa9dee732a", + "tag": "v20261106.01", "machine": "v20261026.01" }, "terraform": { @@ -20,5 +20,5 @@ "endToEnd": 79, "gap": 6 }, - "openapiSha256": "7550d0c634c6ebaaffb877af8073dbca698aa2c3c0e9f096c7739454c32ca690" + "openapiSha256": "2c0df30bc095c02d4c0a21fa51cbd3c25606199c67eb7be74a62776c3abc1d64" } diff --git a/src/data/shots.json b/src/data/shots.json index 384b883..26c55fc 100644 --- a/src/data/shots.json +++ b/src/data/shots.json @@ -1,6 +1,6 @@ { - "release": "v20261104.01", - "commit": "2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9", + "release": "v20261106.01", + "commit": "3cb9bb55ff21e9b9ff669480dc9053aa9dee732a", "shots": [ { "name": "workspaces", diff --git a/versions.yaml b/versions.yaml index ed975cf..5d64fbc 100644 --- a/versions.yaml +++ b/versions.yaml @@ -7,8 +7,8 @@ - name: spin kind: git source: https://github.com/spin-stack/spin - version: v20261104.01 - pin: 2cfbcd74db9e1b599cc29f342d1d35ce1dbe1be9 + version: v20261106.01 + pin: 3cb9bb55ff21e9b9ff669480dc9053aa9dee732a track: github-release note: >- The release the site documents (D2: the newest, exactly). The daily sync moves it to the next