diff --git a/public/openapi.json b/public/openapi.json index 98787ec..6e45cb6 100644 --- a/public/openapi.json +++ b/public/openapi.json @@ -11063,7 +11063,10 @@ "enum": [ "NULL_VALUE" ], - "description": "Represents a JSON `null`.\n\n `NullValue` is a sentinel, using an enum with only one value to represent\n the null value for the `Value` type union.\n\n A field of type `NullValue` with any value other than `0` is considered\n invalid. Most ProtoJSON serializers will emit a Value with a `null_value` set\n as a JSON `null` regardless of the integer value, and so will round trip to\n a `0` value." + "description": "Represents a JSON `null`.\n\n `NullValue` is a sentinel, using an enum with only one value to represent\n the null value for the `Value` type union.\n\n A field of type `NullValue` with any value other than `0` is considered\n invalid. Most ProtoJSON serializers will emit a Value with a `null_value` set\n as a JSON `null` regardless of the integer value, and so will round trip to\n a `0` value.\n\n- `NULL_VALUE`: Null value.", + "x-enum-descriptions": [ + "Null value." + ] }, "google.protobuf.Struct": { "type": "object", @@ -11379,7 +11382,12 @@ "ALLOWED_EMAIL_TYPE_EMAIL", "ALLOWED_EMAIL_TYPE_DOMAIN" ], - "description": "Allowed email type enum" + "description": "Allowed email type enum\n\n- `ALLOWED_EMAIL_TYPE_EMAIL`: Exact email address match\n- `ALLOWED_EMAIL_TYPE_DOMAIN`: Domain suffix match (@domain.com)", + "x-enum-descriptions": [ + "", + "Exact email address match", + "Domain suffix match (@domain.com)" + ] }, "spin.v1.ApproveWorkspaceSignInRequest": { "type": "object", @@ -11681,7 +11689,13 @@ "BURST_MODE_TO_PRESET", "BURST_MODE_TO_HOST" ], - "description": "BurstMode is how a workspace of a preset may grow past what it starts with." + "description": "BurstMode is how a workspace of a preset may grow past what it starts with.\n\n- `BURST_MODE_FIXED`: FIXED starts at the preset's size and stays there.\n- `BURST_MODE_TO_PRESET`: TO_PRESET starts at the preset's burst floor and may grow to its size.\n- `BURST_MODE_TO_HOST`: TO_HOST starts at the preset's burst floor and may grow to everything its host has.", + "x-enum-descriptions": [ + "", + "FIXED starts at the preset's size and stays there.", + "TO_PRESET starts at the preset's burst floor and may grow to its size.", + "TO_HOST starts at the preset's burst floor and may grow to everything its host has." + ] }, "spin.v1.ChangePasswordRequest": { "type": "object", @@ -12062,7 +12076,14 @@ "CONFIG_ITEM_KIND_PRESET", "CONFIG_ITEM_KIND_POLICY" ], - "description": "What one item of the installation's config file is." + "description": "What one item of the installation's config file is.\n\n- `CONFIG_ITEM_KIND_SETTING`: A setting, by its key: registration_mode, default_network_tags, allowed_images...\n- `CONFIG_ITEM_KIND_EMAIL`: An address or domain registration admits, by itself.", + "x-enum-descriptions": [ + "", + "A setting, by its key: registration_mode, default_network_tags, allowed_images...", + "An address or domain registration admits, by itself.", + "", + "" + ] }, "spin.v1.ConfigureGitHubOAuthRequest": { "type": "object", @@ -12932,6 +12953,14 @@ "DEVICE_LOGIN_STATUS_COMPLETE", "DEVICE_LOGIN_STATUS_EXPIRED", "DEVICE_LOGIN_STATUS_DENIED" + ], + "description": "- `DEVICE_LOGIN_STATUS_PENDING`: User hasn't completed login yet\n- `DEVICE_LOGIN_STATUS_COMPLETE`: Login complete, token available\n- `DEVICE_LOGIN_STATUS_EXPIRED`: Device code expired\n- `DEVICE_LOGIN_STATUS_DENIED`: User denied the request", + "x-enum-descriptions": [ + "", + "User hasn't completed login yet", + "Login complete, token available", + "Device code expired", + "User denied the request" ] }, "spin.v1.DiffSnapshotsRequest": { @@ -13337,6 +13366,14 @@ "FILE_CHANGE_KIND_REMOVED", "FILE_CHANGE_KIND_MODIFIED", "FILE_CHANGE_KIND_TYPE_CHANGED" + ], + "description": "- `FILE_CHANGE_KIND_MODIFIED`: The same type on both sides, and a different content, mode, owner or symlink target.", + "x-enum-descriptions": [ + "", + "", + "", + "The same type on both sides, and a different content, mode, owner or symlink target.", + "" ] }, "spin.v1.FileState": { @@ -13404,6 +13441,14 @@ "FILE_TYPE_DIRECTORY", "FILE_TYPE_SYMLINK", "FILE_TYPE_OTHER" + ], + "description": "- `FILE_TYPE_OTHER`: A device, a FIFO or a socket.", + "x-enum-descriptions": [ + "", + "", + "", + "", + "A device, a FIFO or a socket." ] }, "spin.v1.FleetHostVersion": { @@ -17249,7 +17294,12 @@ "OUTSIDE_SHARE_STATE_PREPARING", "OUTSIDE_SHARE_STATE_READY" ], - "description": "OutsideShareState is how far a snapshot's share outside its team is." + "description": "OutsideShareState is how far a snapshot's share outside its team is.\n\n- `OUTSIDE_SHARE_STATE_UNSPECIFIED`: None: the snapshot was never shared outside its team, nor made public.\n- `OUTSIDE_SHARE_STATE_PREPARING`: A host is writing the keys a clone outside the team reads the snapshot with.\n- `OUTSIDE_SHARE_STATE_READY`: Somebody of another team can create a workspace from it.", + "x-enum-descriptions": [ + "None: the snapshot was never shared outside its team, nor made public.", + "A host is writing the keys a clone outside the team reads the snapshot with.", + "Somebody of another team can create a workspace from it." + ] }, "spin.v1.OwnerWord": { "type": "object", @@ -17437,6 +17487,12 @@ "PLATFORM_IMAGE_ARTIFACT_UNSPECIFIED", "PLATFORM_IMAGE_ARTIFACT_BASE", "PLATFORM_IMAGE_ARTIFACT_SUPERVISOR" + ], + "description": "- `PLATFORM_IMAGE_ARTIFACT_BASE`: The machine's base image, every workspace's disk's floor.\n- `PLATFORM_IMAGE_ARTIFACT_SUPERVISOR`: The supervisor extension every workspace is handed.", + "x-enum-descriptions": [ + "", + "The machine's base image, every workspace's disk's floor.", + "The supervisor extension every workspace is handed." ] }, "spin.v1.PlatformImageState": { @@ -17450,6 +17506,16 @@ "PLATFORM_IMAGE_STATE_FAILED", "PLATFORM_IMAGE_STATE_UNAVAILABLE", "PLATFORM_IMAGE_STATE_FOREIGN" + ], + "description": "- `PLATFORM_IMAGE_STATE_UNAVAILABLE`: This build carries nothing to publish.\n- `PLATFORM_IMAGE_STATE_FOREIGN`: The ref names an image somebody else published, which is left as it is.", + "x-enum-descriptions": [ + "", + "", + "", + "", + "", + "This build carries nothing to publish.", + "The ref names an image somebody else published, which is left as it is." ] }, "spin.v1.PlatformLogFieldValuesRequest": { @@ -17518,7 +17584,13 @@ "PORT_ACCESS_WHITELIST", "PORT_ACCESS_PUBLIC" ], - "description": "Who may reach a published port.\n\n Per port rather than per workspace: one workspace serves a demo anyone may see and an\n admin panel only its owner may, and a single setting for both makes the safe answer for\n one the wrong answer for the other.\n\n UNSPECIFIED is not a level and is never stored - the column's CHECK excludes it. A\n request that leaves it at proto3's zero is treated as PRIVATE, which is the direction to\n be wrong in: the cost of failing closed is a confusing error, and the cost of failing\n open is a port somebody published without meaning to." + "description": "Who may reach a published port.\n\n Per port rather than per workspace: one workspace serves a demo anyone may see and an\n admin panel only its owner may, and a single setting for both makes the safe answer for\n one the wrong answer for the other.\n\n UNSPECIFIED is not a level and is never stored - the column's CHECK excludes it. A\n request that leaves it at proto3's zero is treated as PRIVATE, which is the direction to\n be wrong in: the cost of failing closed is a confusing error, and the cost of failing\n open is a port somebody published without meaning to.\n\n- `PORT_ACCESS_PRIVATE`: Only the workspace's owner, who must be signed in.\n- `PORT_ACCESS_WHITELIST`: The owner, and the users the owner granted. See GrantPortAccess.\n- `PORT_ACCESS_PUBLIC`: Anyone, with no session at all. Nothing is asked and nobody is redirected to a login.\n Until the workspace stops or fails: then the port is PRIVATE again, and made public again\n when it is meant to be.", + "x-enum-descriptions": [ + "", + "Only the workspace's owner, who must be signed in.", + "The owner, and the users the owner granted. See GrantPortAccess.", + "Anyone, with no session at all. Nothing is asked and nobody is redirected to a login.\n Until the workspace stops or fails: then the port is PRIVATE again, and made public again\n when it is meant to be." + ] }, "spin.v1.PortGrant": { "type": "object", @@ -17640,6 +17712,14 @@ "PREBUILD_STATE_READY", "PREBUILD_STATE_FAILED", "PREBUILD_STATE_RETIRED" + ], + "description": "- `PREBUILD_STATE_RETIRED`: Superseded and given back: its snapshot is being deleted.", + "x-enum-descriptions": [ + "", + "", + "", + "", + "Superseded and given back: its snapshot is being deleted." ] }, "spin.v1.PreemptionSource": { @@ -17968,7 +18048,13 @@ "REGISTRATION_MODE_WHITELIST", "REGISTRATION_MODE_CLOSED" ], - "description": "Registration mode enum" + "description": "Registration mode enum\n\n- `REGISTRATION_MODE_OPEN`: Anyone can register\n- `REGISTRATION_MODE_WHITELIST`: Only whitelisted emails/domains\n- `REGISTRATION_MODE_CLOSED`: No new registrations", + "x-enum-descriptions": [ + "", + "Anyone can register", + "Only whitelisted emails/domains", + "No new registrations" + ] }, "spin.v1.RegistrationToken": { "type": "object", @@ -18048,7 +18134,13 @@ "REKEY_STATE_COPYING", "REKEY_STATE_READY" ], - "description": "RekeyState is how far a disk's re-key is." + "description": "RekeyState is how far a disk's re-key is.\n\n- `REKEY_STATE_PENDING`: Marked by a revoke: re-keyed once its workspace cannot run.\n- `REKEY_STATE_COPYING`: A host is copying the disk.\n- `REKEY_STATE_READY`: Copied: the workspace is pointed at the copy and the disk deleted on the next pass.", + "x-enum-descriptions": [ + "", + "Marked by a revoke: re-keyed once its workspace cannot run.", + "A host is copying the disk.", + "Copied: the workspace is pointed at the copy and the disk deleted on the next pass." + ] }, "spin.v1.RekeyVolumeRequest": { "type": "object", @@ -19445,6 +19537,12 @@ "SIGNATURE_KIND_UNSPECIFIED", "SIGNATURE_KIND_KEYRING", "SIGNATURE_KIND_ROSTER" + ], + "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.", + "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." ] }, "spin.v1.SignedDocument": { @@ -19541,7 +19639,13 @@ "SNAPSHOT_ACCESS_TYPE_SHARED", "SNAPSHOT_ACCESS_TYPE_PUBLIC" ], - "description": "Access type for snapshots" + "description": "Access type for snapshots\n\n- `SNAPSHOT_ACCESS_TYPE_OWNER`: Owner of the source workspace\n- `SNAPSHOT_ACCESS_TYPE_SHARED`: Explicitly shared with user\n- `SNAPSHOT_ACCESS_TYPE_PUBLIC`: Public snapshot", + "x-enum-descriptions": [ + "", + "Owner of the source workspace", + "Explicitly shared with user", + "Public snapshot" + ] }, "spin.v1.SnapshotShare": { "type": "object", @@ -19593,7 +19697,14 @@ "SNAPSHOT_STATE_FAILED", "SNAPSHOT_STATE_DELETING" ], - "description": "How far along a snapshot is. A snapshot is taken by the host serving the volume, so it\n exists before it is usable: CREATING is the window between asking for one and the host\n reporting the commit it published." + "description": "How far along a snapshot is. A snapshot is taken by the host serving the volume, so it\n exists before it is usable: CREATING is the window between asking for one and the host\n reporting the commit it published.\n\n- `SNAPSHOT_STATE_CREATING`: Requested; the host has not published a commit yet\n- `SNAPSHOT_STATE_PUBLISHED`: Usable: a workspace can be created from it", + "x-enum-descriptions": [ + "", + "Requested; the host has not published a commit yet", + "Usable: a workspace can be created from it", + "", + "" + ] }, "spin.v1.Span": { "type": "object", @@ -19819,6 +19930,15 @@ "STATUS_DISAGREEMENT_KIND_HOST_UNREACHABLE", "STATUS_DISAGREEMENT_KIND_VOLUME_REFUSING", "STATUS_DISAGREEMENT_KIND_UNHEALTHY" + ], + "description": "- `STATUS_DISAGREEMENT_KIND_SUPERVISOR_STALE`: The control plane says the workspace runs and the supervisor has gone quiet for longer\n than several heartbeat intervals.\n- `STATUS_DISAGREEMENT_KIND_SUPERVISOR_ABSENT`: The control plane says the workspace runs and no supervisor ever reported.\n- `STATUS_DISAGREEMENT_KIND_HOST_UNREACHABLE`: The host holding this workspace is not ACTIVE, or has stopped heartbeating.\n- `STATUS_DISAGREEMENT_KIND_VOLUME_REFUSING`: The volume under the workspace is refusing to serve.\n- `STATUS_DISAGREEMENT_KIND_UNHEALTHY`: The supervisor reports a failing health check.", + "x-enum-descriptions": [ + "", + "The control plane says the workspace runs and the supervisor has gone quiet for longer\n than several heartbeat intervals.", + "The control plane says the workspace runs and no supervisor ever reported.", + "The host holding this workspace is not ACTIVE, or has stopped heartbeating.", + "The volume under the workspace is refusing to serve.", + "The supervisor reports a failing health check." ] }, "spin.v1.StopWorkspaceRequest": { @@ -19999,6 +20119,15 @@ "STORED_VOLUME_KIND_EXTENSION", "STORED_VOLUME_KIND_UNCLAIMED", "STORED_VOLUME_KIND_ORPHAN" + ], + "description": "- `STORED_VOLUME_KIND_WORKSPACE`: A workspace's disk, now or before.\n- `STORED_VOLUME_KIND_IMAGE`: An image a workspace's disk is cloned from.\n- `STORED_VOLUME_KIND_EXTENSION`: A release of an extension: the supervisor, the VS Code servers.\n- `STORED_VOLUME_KIND_UNCLAIMED`: A volume the database has and nothing names: a clone being made, or a delete not finished.\n- `STORED_VOLUME_KIND_ORPHAN`: Objects under a volume the database does not have.", + "x-enum-descriptions": [ + "", + "A workspace's disk, now or before.", + "An image a workspace's disk is cloned from.", + "A release of an extension: the supervisor, the VS Code servers.", + "A volume the database has and nothing names: a clone being made, or a delete not finished.", + "Objects under a volume the database does not have." ] }, "spin.v1.SubmitSignatureRequest": { @@ -20325,7 +20454,13 @@ "TEAM_ROLE_ADMIN", "TEAM_ROLE_MEMBER" ], - "description": "Team member role enum" + "description": "Team member role enum\n\n- `TEAM_ROLE_OWNER`: Full control, can delete team\n- `TEAM_ROLE_ADMIN`: Can manage members and settings\n- `TEAM_ROLE_MEMBER`: Can create workspaces, view team resources", + "x-enum-descriptions": [ + "", + "Full control, can delete team", + "Can manage members and settings", + "Can create workspaces, view team resources" + ] }, "spin.v1.TeamSecret": { "type": "object", @@ -21244,6 +21379,14 @@ "VS_CODE_SERVER_PUBLISH_STATE_WORKING", "VS_CODE_SERVER_PUBLISH_STATE_PUBLISHED", "VS_CODE_SERVER_PUBLISH_STATE_FAILED" + ], + "description": "- `VS_CODE_SERVER_PUBLISH_STATE_IDLE`: Nothing published since this control plane started.", + "x-enum-descriptions": [ + "", + "Nothing published since this control plane started.", + "", + "", + "" ] }, "spin.v1.ValidateTaskfileRequest": { @@ -21667,7 +21810,17 @@ "WORKSPACE_ACTION_SUSPEND", "WORKSPACE_ACTION_START_FROM_DISK" ], - "description": "WorkspaceAction is an act a person can ask of a workspace." + "description": "WorkspaceAction is an act a person can ask of a workspace.\n\n- `WORKSPACE_ACTION_FORCE_STOP`: Stop without waiting for the guest: also what ends a stop that does not finish.\n- `WORKSPACE_ACTION_SUSPEND`: Put down with its memory, to be resumed where it was.\n- `WORKSPACE_ACTION_START_FROM_DISK`: Boot a suspended workspace from its disk, dropping its memory (StartWorkspaceRequest.from_disk):\n offered when that memory's machine is run by no host (Workspace.memory_machine_gone).", + "x-enum-descriptions": [ + "", + "", + "", + "Stop without waiting for the guest: also what ends a stop that does not finish.", + "", + "", + "Put down with its memory, to be resumed where it was.", + "Boot a suspended workspace from its disk, dropping its memory (StartWorkspaceRequest.from_disk):\n offered when that memory's machine is run by no host (Workspace.memory_machine_gone)." + ] }, "spin.v1.WorkspaceCost": { "type": "object", @@ -21837,6 +21990,32 @@ "WORKSPACE_EVENT_TYPE_SUSPENSION_DUE", "WORKSPACE_EVENT_TYPE_KEPT", "WORKSPACE_EVENT_TYPE_UNRESPONSIVE" + ], + "description": "- `WORKSPACE_EVENT_TYPE_CREATED`: Workspace was created\n- `WORKSPACE_EVENT_TYPE_STARTED`: Workspace was started\n- `WORKSPACE_EVENT_TYPE_STOPPED`: Workspace was stopped; its disk is kept, and no snapshot is taken\n- `WORKSPACE_EVENT_TYPE_SNAPSHOT_CREATED`: Manual snapshot\n- `WORKSPACE_EVENT_TYPE_DELETED`: Workspace was deleted\n- `WORKSPACE_EVENT_TYPE_FAILED`: Workspace start failed\n- `WORKSPACE_EVENT_TYPE_RESTORED`: Its disk was put back to a snapshot\n- `WORKSPACE_EVENT_TYPE_RESUMED`: It went on from a snapshot's memory\n- `WORKSPACE_EVENT_TYPE_BOOTED`: Suspended, its memory could not be resumed, and its disk was booted\n- `WORKSPACE_EVENT_TYPE_QUARANTINED`: An administrator held it: stopped, and startable by nobody until released\n- `WORKSPACE_EVENT_TYPE_UNQUARANTINED`: The hold was released: back to stopped, where it was held from\n- `WORKSPACE_EVENT_TYPE_PLACED`: A workspace that waited for a host was given one, and its disk there\n- `WORKSPACE_EVENT_TYPE_TRASHED`: Deleted into the trash: its disk kept, its owner able to undelete it\n- `WORKSPACE_EVENT_TYPE_UNDELETED`: Taken back out of the trash\n- `WORKSPACE_EVENT_TYPE_MOVED`: Suspended on its host and resumed on another, which had room for what it was granted\n- `WORKSPACE_EVENT_TYPE_DISPLACED`: Its host was drained or went away: suspended there, it is resumed on another on its own\n- `WORKSPACE_EVENT_TYPE_STOP_BACKUP_FAILED`: A stop on a host that can be taken away could not publish its disk first, so it runs on\n- `WORKSPACE_EVENT_TYPE_IDLE_SUSPENDED`: Nobody used it for as long as the installation allows: suspended with its processes, a start resumes them\n- `WORKSPACE_EVENT_TYPE_RUNNING_CAP_SUSPENDED`: It ran at a stretch for as long as the installation allows: suspended with its processes, a start resumes them\n- `WORKSPACE_EVENT_TYPE_SUSPENSION_DUE`: A suspension is minutes away and the question was asked: its terminals, its page, the CLI; a keep answers it\n- `WORKSPACE_EVENT_TYPE_KEPT`: Somebody kept it awake until a time: no suspension before it\n- `WORKSPACE_EVENT_TYPE_UNRESPONSIVE`: Its supervisor said nothing for longer than the control plane waits: stopped by force, and a start brings it back", + "x-enum-descriptions": [ + "", + "Workspace was created", + "Workspace was started", + "Workspace was stopped; its disk is kept, and no snapshot is taken", + "Manual snapshot", + "Workspace was deleted", + "Workspace start failed", + "Its disk was put back to a snapshot", + "It went on from a snapshot's memory", + "Suspended, its memory could not be resumed, and its disk was booted", + "An administrator held it: stopped, and startable by nobody until released", + "The hold was released: back to stopped, where it was held from", + "A workspace that waited for a host was given one, and its disk there", + "Deleted into the trash: its disk kept, its owner able to undelete it", + "Taken back out of the trash", + "Suspended on its host and resumed on another, which had room for what it was granted", + "Its host was drained or went away: suspended there, it is resumed on another on its own", + "A stop on a host that can be taken away could not publish its disk first, so it runs on", + "Nobody used it for as long as the installation allows: suspended with its processes, a start resumes them", + "It ran at a stretch for as long as the installation allows: suspended with its processes, a start resumes them", + "A suspension is minutes away and the question was asked: its terminals, its page, the CLI; a keep answers it", + "Somebody kept it awake until a time: no suspension before it", + "Its supervisor said nothing for longer than the control plane waits: stopped by force, and a start brings it back" ] }, "spin.v1.WorkspaceFailure": { @@ -21857,7 +22036,22 @@ "WORKSPACE_FAILURE_NO_HOST", "WORKSPACE_FAILURE_MACHINE_CHANGED" ], - "description": "WorkspaceFailure is why a FAILED workspace failed: which part of its run, closed so what a\n person can do about it - and a failure rate split by the repair it needs - is decided by the\n kind rather than by the text of an error. The reason beside it is the detail.\n\n One enum for the client and the host's report (spin.agent.v1.ObservedWorkspace): the kind a\n person is shown is the one the host named, with no second list to keep in step." + "description": "WorkspaceFailure is why a FAILED workspace failed: which part of its run, closed so what a\n person can do about it - and a failure rate split by the repair it needs - is decided by the\n kind rather than by the text of an error. The reason beside it is the detail.\n\n One enum for the client and the host's report (spin.agent.v1.ObservedWorkspace): the kind a\n person is shown is the one the host named, with no second list to keep in step.\n\n- `WORKSPACE_FAILURE_UNSPECIFIED`: Not classified. A failure that lands here is a site missing its classification.\n- `WORKSPACE_FAILURE_VOLUME`: Its disk could not be served or made: the host is not serving its volume (its refusal says\n why), or what the disk was to be made from is gone.\n- `WORKSPACE_FAILURE_EXTENSION`: An extension could not be attached, or the releases it starts with could not be named.\n- `WORKSPACE_FAILURE_NETWORK`: The machine's network namespace or its tags could not be set up.\n- `WORKSPACE_FAILURE_RESOURCES`: The machine could not be given the cores or memory it was asked for.\n- `WORKSPACE_FAILURE_MACHINE`: QEMU could not be prepared or did not boot.\n- `WORKSPACE_FAILURE_GUEST`: The guest booted and did not take its identity or its own filesystem.\n- `WORKSPACE_FAILURE_RELEASE_GONE`: A resume needs an extension release that is no longer in the object store: the memory\n cannot be resumed anywhere, and the control plane boots the disk with the newest releases.\n- `WORKSPACE_FAILURE_EXITED`: The machine ended without being asked to: its guest powered off, or its QEMU crashed or was\n killed.\n- `WORKSPACE_FAILURE_STOP`: The machine could not be stopped or removed.\n- `WORKSPACE_FAILURE_TIMED_OUT`: Its host did not bring a start or a stop to an end before the deadline: unreachable, or its\n attempts outlasted it. The control plane's verdict (the stuck sweep), never a host's.\n- `WORKSPACE_FAILURE_NO_HOST`: No host could take it: none came with room while it waited, or its disk is only on a host\n that is not connected. The control plane's verdict, never a host's.\n- `WORKSPACE_FAILURE_MACHINE_CHANGED`: Its memory was taken on a machine no host of the installation runs now: the machine's\n contract moved (a release that changed it), or the processor did. The memory resumes nowhere;\n the workspace stays suspended, and booting it from its disk, which drops the memory, is its\n owner's to choose (StartWorkspaceRequest.from_disk).", + "x-enum-descriptions": [ + "Not classified. A failure that lands here is a site missing its classification.", + "Its disk could not be served or made: the host is not serving its volume (its refusal says\n why), or what the disk was to be made from is gone.", + "An extension could not be attached, or the releases it starts with could not be named.", + "The machine's network namespace or its tags could not be set up.", + "The machine could not be given the cores or memory it was asked for.", + "QEMU could not be prepared or did not boot.", + "The guest booted and did not take its identity or its own filesystem.", + "A resume needs an extension release that is no longer in the object store: the memory\n cannot be resumed anywhere, and the control plane boots the disk with the newest releases.", + "The machine ended without being asked to: its guest powered off, or its QEMU crashed or was\n killed.", + "The machine could not be stopped or removed.", + "Its host did not bring a start or a stop to an end before the deadline: unreachable, or its\n attempts outlasted it. The control plane's verdict (the stuck sweep), never a host's.", + "No host could take it: none came with room while it waited, or its disk is only on a host\n that is not connected. The control plane's verdict, never a host's.", + "Its memory was taken on a machine no host of the installation runs now: the machine's\n contract moved (a release that changed it), or the processor did. The memory resumes nowhere;\n the workspace stays suspended, and booting it from its disk, which drops the memory, is its\n owner's to choose (StartWorkspaceRequest.from_disk)." + ] }, "spin.v1.WorkspaceHostStatus": { "type": "object", @@ -21989,7 +22183,17 @@ "WORKSPACE_PHASE_GUEST", "WORKSPACE_PHASE_BACKUP" ], - "description": "WorkspacePhase is what a host is doing to bring a workspace up." + "description": "WorkspacePhase is what a host is doing to bring a workspace up.\n\n- `WORKSPACE_PHASE_DISK`: Waiting for its disk to be served on the host.\n- `WORKSPACE_PHASE_EXTENSIONS`: Holding the extension releases it runs with.\n- `WORKSPACE_PHASE_NETWORK`: Setting up its network.\n- `WORKSPACE_PHASE_MACHINE`: Booting its machine, or resuming it from a checkpoint.\n- `WORKSPACE_PHASE_FIRST_BOOT`: Its first boot of a disk another person's workspace was cloned from.\n- `WORKSPACE_PHASE_GUEST`: The machine is up and its workspace inside is starting.\n- `WORKSPACE_PHASE_BACKUP`: Stopping on a host that can be taken away: its disk is being published before the machine\n stops, the control plane's doing rather than the host's, and retried if it restarts.", + "x-enum-descriptions": [ + "", + "Waiting for its disk to be served on the host.", + "Holding the extension releases it runs with.", + "Setting up its network.", + "Booting its machine, or resuming it from a checkpoint.", + "Its first boot of a disk another person's workspace was cloned from.", + "The machine is up and its workspace inside is starting.", + "Stopping on a host that can be taken away: its disk is being published before the machine\n stops, the control plane's doing rather than the host's, and retried if it restarts." + ] }, "spin.v1.WorkspaceProgress": { "type": "object", @@ -22060,7 +22264,15 @@ "WORKSPACE_PROXY_STATUS_PORT_NOT_EXPOSED", "WORKSPACE_PROXY_STATUS_WAKING" ], - "description": "Proxy status for workspace access" + "description": "Proxy status for workspace access\n\n- `WORKSPACE_PROXY_STATUS_ACCESSIBLE`: Port exposed, workspace running\n- `WORKSPACE_PROXY_STATUS_NOT_RUNNING`: Return 503\n- `WORKSPACE_PROXY_STATUS_NOT_FOUND`: Return 404\n- `WORKSPACE_PROXY_STATUS_PORT_NOT_EXPOSED`: Return 403\n- `WORKSPACE_PROXY_STATUS_WAKING`: Not running, and woken for this caller (Workspace.wake_on_access): the proxy opens a session,\n which resumes it and waits a while, and shows a page that asks again while it is not up.", + "x-enum-descriptions": [ + "", + "Port exposed, workspace running", + "Return 503", + "Return 404", + "Return 403", + "Not running, and woken for this caller (Workspace.wake_on_access): the proxy opens a session,\n which resumes it and waits a while, and shows a page that asks again while it is not up." + ] }, "spin.v1.WorkspaceRuntime": { "type": "object", @@ -22113,7 +22325,19 @@ "WORKSPACE_STATE_WAITING", "WORKSPACE_STATE_QUARANTINED" ], - "description": "Workspace states" + "description": "WorkspaceState is where a workspace is in its life. Each value's comment is what the API's\n document says of it (buf.gen.openapi.yaml's with-enum-value-descriptions), and the website's\n table of states is generated from it: it is written for a person reading that table, in the\n site's words (a runner, the CLI's commands). Why a value is what it is goes in a comment\n apart, above the value's own, which the document does not carry.\n\n- `WORKSPACE_STATE_UNSPECIFIED`: Never a workspace's state: a client that reads it read a field nothing set.\n- `WORKSPACE_STATE_CREATING`: The workspace exists and has not run yet.\n- `WORKSPACE_STATE_STARTING`: A runner is preparing its disk and starting its machine.\n- `WORKSPACE_STATE_RUNNING`: Its machine is up.\n- `WORKSPACE_STATE_STOPPING`: Its machine is shutting down, and then what its disk wrote since its last commit is\n uploaded to the bucket. A stop stays here until the upload is done, and says why it is not;\n `spin workspace stop --force` does not wait for it.\n- `WORKSPACE_STATE_STOPPED`: Not running. Its disk is kept, and the next start boots from it.\n- `WORKSPACE_STATE_FAILED`: A start or a stop failed: `spin workspace status` says which part, and why. It stays so\n until it is started again.\n- `WORKSPACE_STATE_DELETED`: In the trash, with its disk, for the days the installation keeps it there\n (`workspace_trash_days`): `spin workspace undelete` brings it back, stopped. An installation\n that keeps no trash erases it at once.\n- `WORKSPACE_STATE_WAITING`: Wanted running, and no runner has room for it yet. On AWS, where runners scale to none, one\n is being started, and the workspace starts on it once it is up.\n- `WORKSPACE_STATE_QUARANTINED`: Held by an administrator with `spin workspace quarantine`: it cannot start until\n `spin workspace unquarantine` releases it, and its disk is kept as it was.", + "x-enum-descriptions": [ + "Never a workspace's state: a client that reads it read a field nothing set.", + "The workspace exists and has not run yet.", + "A runner is preparing its disk and starting its machine.", + "Its machine is up.", + "Its machine is shutting down, and then what its disk wrote since its last commit is\n uploaded to the bucket. A stop stays here until the upload is done, and says why it is not;\n `spin workspace stop --force` does not wait for it.", + "Not running. Its disk is kept, and the next start boots from it.", + "A start or a stop failed: `spin workspace status` says which part, and why. It stays so\n until it is started again.", + "In the trash, with its disk, for the days the installation keeps it there\n (`workspace_trash_days`): `spin workspace undelete` brings it back, stopped. An installation\n that keeps no trash erases it at once.", + "Wanted running, and no runner has room for it yet. On AWS, where runners scale to none, one\n is being started, and the workspace starts on it once it is up.", + "Held by an administrator with `spin workspace quarantine`: it cannot start until\n `spin workspace unquarantine` releases it, and its disk is kept as it was." + ] }, "spin.v1.WorkspaceSuspendFailure": { "type": "object", diff --git a/src/assets/shots/workspace.png b/src/assets/shots/workspace.png index a3f80da..f6c8782 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 1206930..6c4c437 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/types.md b/src/content/docs/reference/api/types.md index e81bfa9..6389790 100644 --- a/src/content/docs/reference/api/types.md +++ b/src/content/docs/reference/api/types.md @@ -45,7 +45,7 @@ Allowed email/domain entry ## AllowedEmailType -Allowed email type enum +Allowed email type enum - `ALLOWED_EMAIL_TYPE_EMAIL`: Exact email address match - `ALLOWED_EMAIL_TYPE_DOMAIN`: Domain suffix match (@domain.com) One of: `ALLOWED_EMAIL_TYPE_UNSPECIFIED`, `ALLOWED_EMAIL_TYPE_EMAIL`, `ALLOWED_EMAIL_TYPE_DOMAIN`. @@ -106,7 +106,7 @@ BrokeredRequest is one request the egress proxy read from the workspace's machin ## BurstMode -BurstMode is how a workspace of a preset may grow past what it starts with. +BurstMode is how a workspace of a preset may grow past what it starts with. - `BURST_MODE_FIXED`: FIXED starts at the preset's size and stays there. - `BURST_MODE_TO_PRESET`: TO_PRESET starts at the preset's burst floor and may grow to its size. - `BURST_MODE_TO_HOST`: TO_HOST starts at the preset's burst floor and may grow to everything its host has. One of: `BURST_MODE_UNSPECIFIED`, `BURST_MODE_FIXED`, `BURST_MODE_TO_PRESET`, `BURST_MODE_TO_HOST`. @@ -134,7 +134,7 @@ One thing the config file says differently from the installation. ## ConfigItemKind -What one item of the installation's config file is. +What one item of the installation's config file is. - `CONFIG_ITEM_KIND_SETTING`: A setting, by its key: registration_mode, default_network_tags, allowed_images... - `CONFIG_ITEM_KIND_EMAIL`: An address or domain registration admits, by itself. One of: `CONFIG_ITEM_KIND_UNSPECIFIED`, `CONFIG_ITEM_KIND_SETTING`, `CONFIG_ITEM_KIND_EMAIL`, `CONFIG_ITEM_KIND_PRESET`, `CONFIG_ITEM_KIND_POLICY`. @@ -151,6 +151,8 @@ DeletedWorkspace is a workspace in the trash. ## DeviceLoginStatus +- `DEVICE_LOGIN_STATUS_PENDING`: User hasn't completed login yet - `DEVICE_LOGIN_STATUS_COMPLETE`: Login complete, token available - `DEVICE_LOGIN_STATUS_EXPIRED`: Device code expired - `DEVICE_LOGIN_STATUS_DENIED`: User denied the request + One of: `DEVICE_LOGIN_STATUS_UNSPECIFIED`, `DEVICE_LOGIN_STATUS_PENDING`, `DEVICE_LOGIN_STATUS_COMPLETE`, `DEVICE_LOGIN_STATUS_EXPIRED`, `DEVICE_LOGIN_STATUS_DENIED`. ## DotfilesConfig @@ -218,6 +220,8 @@ FieldValue is one value a field has, and how many of a search's records have it. ## FileChangeKind +- `FILE_CHANGE_KIND_MODIFIED`: The same type on both sides, and a different content, mode, owner or symlink target. + One of: `FILE_CHANGE_KIND_UNSPECIFIED`, `FILE_CHANGE_KIND_ADDED`, `FILE_CHANGE_KIND_REMOVED`, `FILE_CHANGE_KIND_MODIFIED`, `FILE_CHANGE_KIND_TYPE_CHANGED`. ## FileState @@ -236,6 +240,8 @@ One of: `FILE_CHANGE_KIND_UNSPECIFIED`, `FILE_CHANGE_KIND_ADDED`, `FILE_CHANGE_K ## FileType +- `FILE_TYPE_OTHER`: A device, a FIFO or a socket. + One of: `FILE_TYPE_UNSPECIFIED`, `FILE_TYPE_REGULAR`, `FILE_TYPE_DIRECTORY`, `FILE_TYPE_SYMLINK`, `FILE_TYPE_OTHER`. ## FleetHostVersion @@ -565,7 +571,7 @@ ObservedDestination is one address the workspace was allowed to reach, with what ## OutsideShareState -OutsideShareState is how far a snapshot's share outside its team is. +OutsideShareState is how far a snapshot's share outside its team is. - `OUTSIDE_SHARE_STATE_UNSPECIFIED`: None: the snapshot was never shared outside its team, nor made public. - `OUTSIDE_SHARE_STATE_PREPARING`: A host is writing the keys a clone outside the team reads the snapshot with. - `OUTSIDE_SHARE_STATE_READY`: Somebody of another team can create a workspace from it. One of: `OUTSIDE_SHARE_STATE_UNSPECIFIED`, `OUTSIDE_SHARE_STATE_PREPARING`, `OUTSIDE_SHARE_STATE_READY`. @@ -618,15 +624,19 @@ PendingSignature is one document the caller is asked to sign. ## PlatformImageArtifact +- `PLATFORM_IMAGE_ARTIFACT_BASE`: The machine's base image, every workspace's disk's floor. - `PLATFORM_IMAGE_ARTIFACT_SUPERVISOR`: The supervisor extension every workspace is handed. + One of: `PLATFORM_IMAGE_ARTIFACT_UNSPECIFIED`, `PLATFORM_IMAGE_ARTIFACT_BASE`, `PLATFORM_IMAGE_ARTIFACT_SUPERVISOR`. ## PlatformImageState +- `PLATFORM_IMAGE_STATE_UNAVAILABLE`: This build carries nothing to publish. - `PLATFORM_IMAGE_STATE_FOREIGN`: The ref names an image somebody else published, which is left as it is. + One of: `PLATFORM_IMAGE_STATE_UNSPECIFIED`, `PLATFORM_IMAGE_STATE_PENDING`, `PLATFORM_IMAGE_STATE_PUBLISHED`, `PLATFORM_IMAGE_STATE_PUBLISHING`, `PLATFORM_IMAGE_STATE_FAILED`, `PLATFORM_IMAGE_STATE_UNAVAILABLE`, `PLATFORM_IMAGE_STATE_FOREIGN`. ## PortAccess -Who may reach a published port. Per port rather than per workspace: one workspace serves a demo anyone may see and an admin panel only its owner may, and a single setting for both makes the safe answer for one the wrong answer for the other. UNSPECIFIED is not a level and is never stored - the column's CHECK excludes it. A request that leaves it at proto3's zero is treated as PRIVATE, which is the direction to be wrong in: the cost of failing closed is a confusing error, and the cost of failing open is a port somebody published without meaning to. +Who may reach a published port. Per port rather than per workspace: one workspace serves a demo anyone may see and an admin panel only its owner may, and a single setting for both makes the safe answer for one the wrong answer for the other. UNSPECIFIED is not a level and is never stored - the column's CHECK excludes it. A request that leaves it at proto3's zero is treated as PRIVATE, which is the direction to be wrong in: the cost of failing closed is a confusing error, and the cost of failing open is a port somebody published without meaning to. - `PORT_ACCESS_PRIVATE`: Only the workspace's owner, who must be signed in. - `PORT_ACCESS_WHITELIST`: The owner, and the users the owner granted. See GrantPortAccess. - `PORT_ACCESS_PUBLIC`: Anyone, with no session at all. Nothing is asked and nobody is redirected to a login. Until the workspace stops or fails: then the port is PRIVATE again, and made public again when it is meant to be. One of: `PORT_ACCESS_UNSPECIFIED`, `PORT_ACCESS_PRIVATE`, `PORT_ACCESS_WHITELIST`, `PORT_ACCESS_PUBLIC`. @@ -664,6 +674,8 @@ A prebuild: one build of a project's ref at a commit, and the snapshot it left. ## PrebuildState +- `PREBUILD_STATE_RETIRED`: Superseded and given back: its snapshot is being deleted. + One of: `PREBUILD_STATE_UNSPECIFIED`, `PREBUILD_STATE_BUILDING`, `PREBUILD_STATE_READY`, `PREBUILD_STATE_FAILED`, `PREBUILD_STATE_RETIRED`. ## PreemptionSource @@ -727,7 +739,7 @@ RateLimitSettings configures API rate limiting ## RegistrationMode -Registration mode enum +Registration mode enum - `REGISTRATION_MODE_OPEN`: Anyone can register - `REGISTRATION_MODE_WHITELIST`: Only whitelisted emails/domains - `REGISTRATION_MODE_CLOSED`: No new registrations One of: `REGISTRATION_MODE_UNSPECIFIED`, `REGISTRATION_MODE_OPEN`, `REGISTRATION_MODE_WHITELIST`, `REGISTRATION_MODE_CLOSED`. @@ -749,7 +761,7 @@ One of: `REGISTRATION_MODE_UNSPECIFIED`, `REGISTRATION_MODE_OPEN`, `REGISTRATION ## RekeyState -RekeyState is how far a disk's re-key is. +RekeyState is how far a disk's re-key is. - `REKEY_STATE_PENDING`: Marked by a revoke: re-keyed once its workspace cannot run. - `REKEY_STATE_COPYING`: A host is copying the disk. - `REKEY_STATE_READY`: Copied: the workspace is pointed at the copy and the disk deleted on the next pass. One of: `REKEY_STATE_UNSPECIFIED`, `REKEY_STATE_PENDING`, `REKEY_STATE_COPYING`, `REKEY_STATE_READY`. @@ -871,6 +883,8 @@ 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. + One of: `SIGNATURE_KIND_UNSPECIFIED`, `SIGNATURE_KIND_KEYRING`, `SIGNATURE_KIND_ROSTER`. ## SignedDocument @@ -901,7 +915,7 @@ A snapshot is a rotation of a workspace's volume, published as a commit. It has ## SnapshotAccessType -Access type for snapshots +Access type for snapshots - `SNAPSHOT_ACCESS_TYPE_OWNER`: Owner of the source workspace - `SNAPSHOT_ACCESS_TYPE_SHARED`: Explicitly shared with user - `SNAPSHOT_ACCESS_TYPE_PUBLIC`: Public snapshot One of: `SNAPSHOT_ACCESS_TYPE_UNSPECIFIED`, `SNAPSHOT_ACCESS_TYPE_OWNER`, `SNAPSHOT_ACCESS_TYPE_SHARED`, `SNAPSHOT_ACCESS_TYPE_PUBLIC`. @@ -921,7 +935,7 @@ A share record for a snapshot ## SnapshotState -How far along a snapshot is. A snapshot is taken by the host serving the volume, so it exists before it is usable: CREATING is the window between asking for one and the host reporting the commit it published. +How far along a snapshot is. A snapshot is taken by the host serving the volume, so it exists before it is usable: CREATING is the window between asking for one and the host reporting the commit it published. - `SNAPSHOT_STATE_CREATING`: Requested; the host has not published a commit yet - `SNAPSHOT_STATE_PUBLISHED`: Usable: a workspace can be created from it One of: `SNAPSHOT_STATE_UNSPECIFIED`, `SNAPSHOT_STATE_CREATING`, `SNAPSHOT_STATE_PUBLISHED`, `SNAPSHOT_STATE_FAILED`, `SNAPSHOT_STATE_DELETING`. @@ -952,6 +966,8 @@ Span is one operation of a trace, as OpenTelemetry names its parts. ## StatusDisagreementKind +- `STATUS_DISAGREEMENT_KIND_SUPERVISOR_STALE`: The control plane says the workspace runs and the supervisor has gone quiet for longer than several heartbeat intervals. - `STATUS_DISAGREEMENT_KIND_SUPERVISOR_ABSENT`: The control plane says the workspace runs and no supervisor ever reported. - `STATUS_DISAGREEMENT_KIND_HOST_UNREACHABLE`: The host holding this workspace is not ACTIVE, or has stopped heartbeating. - `STATUS_DISAGREEMENT_KIND_VOLUME_REFUSING`: The volume under the workspace is refusing to serve. - `STATUS_DISAGREEMENT_KIND_UNHEALTHY`: The supervisor reports a failing health check. + One of: `STATUS_DISAGREEMENT_KIND_UNSPECIFIED`, `STATUS_DISAGREEMENT_KIND_SUPERVISOR_STALE`, `STATUS_DISAGREEMENT_KIND_SUPERVISOR_ABSENT`, `STATUS_DISAGREEMENT_KIND_HOST_UNREACHABLE`, `STATUS_DISAGREEMENT_KIND_VOLUME_REFUSING`, `STATUS_DISAGREEMENT_KIND_UNHEALTHY`. ## StorageSettings @@ -996,6 +1012,8 @@ StoredVolume is one volume in the store: what is under volumes/<volume_id>/, ## StoredVolumeKind +- `STORED_VOLUME_KIND_WORKSPACE`: A workspace's disk, now or before. - `STORED_VOLUME_KIND_IMAGE`: An image a workspace's disk is cloned from. - `STORED_VOLUME_KIND_EXTENSION`: A release of an extension: the supervisor, the VS Code servers. - `STORED_VOLUME_KIND_UNCLAIMED`: A volume the database has and nothing names: a clone being made, or a delete not finished. - `STORED_VOLUME_KIND_ORPHAN`: Objects under a volume the database does not have. + One of: `STORED_VOLUME_KIND_UNSPECIFIED`, `STORED_VOLUME_KIND_WORKSPACE`, `STORED_VOLUME_KIND_IMAGE`, `STORED_VOLUME_KIND_EXTENSION`, `STORED_VOLUME_KIND_UNCLAIMED`, `STORED_VOLUME_KIND_ORPHAN`. ## SupervisorState @@ -1070,7 +1088,7 @@ What the supervisor inside the guest last reported. Absent (`connected` false wi ## TeamRole -Team member role enum +Team member role enum - `TEAM_ROLE_OWNER`: Full control, can delete team - `TEAM_ROLE_ADMIN`: Can manage members and settings - `TEAM_ROLE_MEMBER`: Can create workspaces, view team resources One of: `TEAM_ROLE_UNSPECIFIED`, `TEAM_ROLE_OWNER`, `TEAM_ROLE_ADMIN`, `TEAM_ROLE_MEMBER`. @@ -1131,6 +1149,8 @@ VSCodeServerPublish is this control plane's publish: the last one, or the one un ## VSCodeServerPublishState +- `VS_CODE_SERVER_PUBLISH_STATE_IDLE`: Nothing published since this control plane started. + One of: `VS_CODE_SERVER_PUBLISH_STATE_UNSPECIFIED`, `VS_CODE_SERVER_PUBLISH_STATE_IDLE`, `VS_CODE_SERVER_PUBLISH_STATE_WORKING`, `VS_CODE_SERVER_PUBLISH_STATE_PUBLISHED`, `VS_CODE_SERVER_PUBLISH_STATE_FAILED`. ## VolumeRekey @@ -1192,7 +1212,7 @@ VolumeRekey is a workspace's disk to re-key or being re-keyed. ## WorkspaceAction -WorkspaceAction is an act a person can ask of a workspace. +WorkspaceAction is an act a person can ask of a workspace. - `WORKSPACE_ACTION_FORCE_STOP`: Stop without waiting for the guest: also what ends a stop that does not finish. - `WORKSPACE_ACTION_SUSPEND`: Put down with its memory, to be resumed where it was. - `WORKSPACE_ACTION_START_FROM_DISK`: Boot a suspended workspace from its disk, dropping its memory (StartWorkspaceRequest.from_disk): offered when that memory's machine is run by no host (Workspace.memory_machine_gone). One of: `WORKSPACE_ACTION_UNSPECIFIED`, `WORKSPACE_ACTION_START`, `WORKSPACE_ACTION_STOP`, `WORKSPACE_ACTION_FORCE_STOP`, `WORKSPACE_ACTION_DELETE`, `WORKSPACE_ACTION_FORCE_DELETE`, `WORKSPACE_ACTION_SUSPEND`, `WORKSPACE_ACTION_START_FROM_DISK`. @@ -1240,11 +1260,13 @@ Timeline event for workspace state changes ## WorkspaceEventType +- `WORKSPACE_EVENT_TYPE_CREATED`: Workspace was created - `WORKSPACE_EVENT_TYPE_STARTED`: Workspace was started - `WORKSPACE_EVENT_TYPE_STOPPED`: Workspace was stopped; its disk is kept, and no snapshot is taken - `WORKSPACE_EVENT_TYPE_SNAPSHOT_CREATED`: Manual snapshot - `WORKSPACE_EVENT_TYPE_DELETED`: Workspace was deleted - `WORKSPACE_EVENT_TYPE_FAILED`: Workspace start failed - `WORKSPACE_EVENT_TYPE_RESTORED`: Its disk was put back to a snapshot - `WORKSPACE_EVENT_TYPE_RESUMED`: It went on from a snapshot's memory - `WORKSPACE_EVENT_TYPE_BOOTED`: Suspended, its memory could not be resumed, and its disk was booted - `WORKSPACE_EVENT_TYPE_QUARANTINED`: An administrator held it: stopped, and startable by nobody until released - `WORKSPACE_EVENT_TYPE_UNQUARANTINED`: The hold was released: back to stopped, where it was held from - `WORKSPACE_EVENT_TYPE_PLACED`: A workspace that waited for a host was given one, and its disk there - `WORKSPACE_EVENT_TYPE_TRASHED`: Deleted into the trash: its disk kept, its owner able to undelete it - `WORKSPACE_EVENT_TYPE_UNDELETED`: Taken back out of the trash - `WORKSPACE_EVENT_TYPE_MOVED`: Suspended on its host and resumed on another, which had room for what it was granted - `WORKSPACE_EVENT_TYPE_DISPLACED`: Its host was drained or went away: suspended there, it is resumed on another on its own - `WORKSPACE_EVENT_TYPE_STOP_BACKUP_FAILED`: A stop on a host that can be taken away could not publish its disk first, so it runs on - `WORKSPACE_EVENT_TYPE_IDLE_SUSPENDED`: Nobody used it for as long as the installation allows: suspended with its processes, a start resumes them - `WORKSPACE_EVENT_TYPE_RUNNING_CAP_SUSPENDED`: It ran at a stretch for as long as the installation allows: suspended with its processes, a start resumes them - `WORKSPACE_EVENT_TYPE_SUSPENSION_DUE`: A suspension is minutes away and the question was asked: its terminals, its page, the CLI; a keep answers it - `WORKSPACE_EVENT_TYPE_KEPT`: Somebody kept it awake until a time: no suspension before it - `WORKSPACE_EVENT_TYPE_UNRESPONSIVE`: Its supervisor said nothing for longer than the control plane waits: stopped by force, and a start brings it back + One of: `WORKSPACE_EVENT_TYPE_UNSPECIFIED`, `WORKSPACE_EVENT_TYPE_CREATED`, `WORKSPACE_EVENT_TYPE_STARTED`, `WORKSPACE_EVENT_TYPE_STOPPED`, `WORKSPACE_EVENT_TYPE_SNAPSHOT_CREATED`, `WORKSPACE_EVENT_TYPE_DELETED`, `WORKSPACE_EVENT_TYPE_FAILED`, `WORKSPACE_EVENT_TYPE_RESTORED`, `WORKSPACE_EVENT_TYPE_RESUMED`, `WORKSPACE_EVENT_TYPE_BOOTED`, `WORKSPACE_EVENT_TYPE_QUARANTINED`, `WORKSPACE_EVENT_TYPE_UNQUARANTINED`, `WORKSPACE_EVENT_TYPE_PLACED`, `WORKSPACE_EVENT_TYPE_TRASHED`, `WORKSPACE_EVENT_TYPE_UNDELETED`, `WORKSPACE_EVENT_TYPE_MOVED`, `WORKSPACE_EVENT_TYPE_DISPLACED`, `WORKSPACE_EVENT_TYPE_STOP_BACKUP_FAILED`, `WORKSPACE_EVENT_TYPE_IDLE_SUSPENDED`, `WORKSPACE_EVENT_TYPE_RUNNING_CAP_SUSPENDED`, `WORKSPACE_EVENT_TYPE_SUSPENSION_DUE`, `WORKSPACE_EVENT_TYPE_KEPT`, `WORKSPACE_EVENT_TYPE_UNRESPONSIVE`. ## WorkspaceFailure -WorkspaceFailure is why a FAILED workspace failed: which part of its run, closed so what a person can do about it - and a failure rate split by the repair it needs - is decided by the kind rather than by the text of an error. The reason beside it is the detail. One enum for the client and the host's report (spin.agent.v1.ObservedWorkspace): the kind a person is shown is the one the host named, with no second list to keep in step. +WorkspaceFailure is why a FAILED workspace failed: which part of its run, closed so what a person can do about it - and a failure rate split by the repair it needs - is decided by the kind rather than by the text of an error. The reason beside it is the detail. One enum for the client and the host's report (spin.agent.v1.ObservedWorkspace): the kind a person is shown is the one the host named, with no second list to keep in step. - `WORKSPACE_FAILURE_UNSPECIFIED`: Not classified. A failure that lands here is a site missing its classification. - `WORKSPACE_FAILURE_VOLUME`: Its disk could not be served or made: the host is not serving its volume (its refusal says why), or what the disk was to be made from is gone. - `WORKSPACE_FAILURE_EXTENSION`: An extension could not be attached, or the releases it starts with could not be named. - `WORKSPACE_FAILURE_NETWORK`: The machine's network namespace or its tags could not be set up. - `WORKSPACE_FAILURE_RESOURCES`: The machine could not be given the cores or memory it was asked for. - `WORKSPACE_FAILURE_MACHINE`: QEMU could not be prepared or did not boot. - `WORKSPACE_FAILURE_GUEST`: The guest booted and did not take its identity or its own filesystem. - `WORKSPACE_FAILURE_RELEASE_GONE`: A resume needs an extension release that is no longer in the object store: the memory cannot be resumed anywhere, and the control plane boots the disk with the newest releases. - `WORKSPACE_FAILURE_EXITED`: The machine ended without being asked to: its guest powered off, or its QEMU crashed or was killed. - `WORKSPACE_FAILURE_STOP`: The machine could not be stopped or removed. - `WORKSPACE_FAILURE_TIMED_OUT`: Its host did not bring a start or a stop to an end before the deadline: unreachable, or its attempts outlasted it. The control plane's verdict (the stuck sweep), never a host's. - `WORKSPACE_FAILURE_NO_HOST`: No host could take it: none came with room while it waited, or its disk is only on a host that is not connected. The control plane's verdict, never a host's. - `WORKSPACE_FAILURE_MACHINE_CHANGED`: Its memory was taken on a machine no host of the installation runs now: the machine's contract moved (a release that changed it), or the processor did. The memory resumes nowhere; the workspace stays suspended, and booting it from its disk, which drops the memory, is its owner's to choose (StartWorkspaceRequest.from_disk). One of: `WORKSPACE_FAILURE_UNSPECIFIED`, `WORKSPACE_FAILURE_VOLUME`, `WORKSPACE_FAILURE_EXTENSION`, `WORKSPACE_FAILURE_NETWORK`, `WORKSPACE_FAILURE_RESOURCES`, `WORKSPACE_FAILURE_MACHINE`, `WORKSPACE_FAILURE_GUEST`, `WORKSPACE_FAILURE_RELEASE_GONE`, `WORKSPACE_FAILURE_EXITED`, `WORKSPACE_FAILURE_STOP`, `WORKSPACE_FAILURE_TIMED_OUT`, `WORKSPACE_FAILURE_NO_HOST`, `WORKSPACE_FAILURE_MACHINE_CHANGED`. @@ -1270,7 +1292,7 @@ WorkspaceLease is a process in the workspace keeping it awake while it lives. ## WorkspacePhase -WorkspacePhase is what a host is doing to bring a workspace up. +WorkspacePhase is what a host is doing to bring a workspace up. - `WORKSPACE_PHASE_DISK`: Waiting for its disk to be served on the host. - `WORKSPACE_PHASE_EXTENSIONS`: Holding the extension releases it runs with. - `WORKSPACE_PHASE_NETWORK`: Setting up its network. - `WORKSPACE_PHASE_MACHINE`: Booting its machine, or resuming it from a checkpoint. - `WORKSPACE_PHASE_FIRST_BOOT`: Its first boot of a disk another person's workspace was cloned from. - `WORKSPACE_PHASE_GUEST`: The machine is up and its workspace inside is starting. - `WORKSPACE_PHASE_BACKUP`: Stopping on a host that can be taken away: its disk is being published before the machine stops, the control plane's doing rather than the host's, and retried if it restarts. One of: `WORKSPACE_PHASE_UNSPECIFIED`, `WORKSPACE_PHASE_DISK`, `WORKSPACE_PHASE_EXTENSIONS`, `WORKSPACE_PHASE_NETWORK`, `WORKSPACE_PHASE_MACHINE`, `WORKSPACE_PHASE_FIRST_BOOT`, `WORKSPACE_PHASE_GUEST`, `WORKSPACE_PHASE_BACKUP`. @@ -1290,7 +1312,7 @@ WorkspaceProgress is a transition under way. ## WorkspaceProxyStatus -Proxy status for workspace access +Proxy status for workspace access - `WORKSPACE_PROXY_STATUS_ACCESSIBLE`: Port exposed, workspace running - `WORKSPACE_PROXY_STATUS_NOT_RUNNING`: Return 503 - `WORKSPACE_PROXY_STATUS_NOT_FOUND`: Return 404 - `WORKSPACE_PROXY_STATUS_PORT_NOT_EXPOSED`: Return 403 - `WORKSPACE_PROXY_STATUS_WAKING`: Not running, and woken for this caller (Workspace.wake_on_access): the proxy opens a session, which resumes it and waits a while, and shows a page that asks again while it is not up. One of: `WORKSPACE_PROXY_STATUS_UNSPECIFIED`, `WORKSPACE_PROXY_STATUS_ACCESSIBLE`, `WORKSPACE_PROXY_STATUS_NOT_RUNNING`, `WORKSPACE_PROXY_STATUS_NOT_FOUND`, `WORKSPACE_PROXY_STATUS_PORT_NOT_EXPOSED`, `WORKSPACE_PROXY_STATUS_WAKING`. @@ -1308,7 +1330,7 @@ WorkspaceRuntime is a running workspace's machine as its host measures it from o ## WorkspaceState -Workspace states +WorkspaceState is where a workspace is in its life. Each value's comment is what the API's document says of it (buf.gen.openapi.yaml's with-enum-value-descriptions), and the website's table of states is generated from it: it is written for a person reading that table, in the site's words (a runner, the CLI's commands). Why a value is what it is goes in a comment apart, above the value's own, which the document does not carry. - `WORKSPACE_STATE_UNSPECIFIED`: Never a workspace's state: a client that reads it read a field nothing set. - `WORKSPACE_STATE_CREATING`: The workspace exists and has not run yet. - `WORKSPACE_STATE_STARTING`: A runner is preparing its disk and starting its machine. - `WORKSPACE_STATE_RUNNING`: Its machine is up. - `WORKSPACE_STATE_STOPPING`: Its machine is shutting down, and then what its disk wrote since its last commit is uploaded to the bucket. A stop stays here until the upload is done, and says why it is not; `spin workspace stop --force` does not wait for it. - `WORKSPACE_STATE_STOPPED`: Not running. Its disk is kept, and the next start boots from it. - `WORKSPACE_STATE_FAILED`: A start or a stop failed: `spin workspace status` says which part, and why. It stays so until it is started again. - `WORKSPACE_STATE_DELETED`: In the trash, with its disk, for the days the installation keeps it there (`workspace_trash_days`): `spin workspace undelete` brings it back, stopped. An installation that keeps no trash erases it at once. - `WORKSPACE_STATE_WAITING`: Wanted running, and no runner has room for it yet. On AWS, where runners scale to none, one is being started, and the workspace starts on it once it is up. - `WORKSPACE_STATE_QUARANTINED`: Held by an administrator with `spin workspace quarantine`: it cannot start until `spin workspace unquarantine` releases it, and its disk is kept as it was. One of: `WORKSPACE_STATE_UNSPECIFIED`, `WORKSPACE_STATE_CREATING`, `WORKSPACE_STATE_STARTING`, `WORKSPACE_STATE_RUNNING`, `WORKSPACE_STATE_STOPPING`, `WORKSPACE_STATE_STOPPED`, `WORKSPACE_STATE_FAILED`, `WORKSPACE_STATE_DELETED`, `WORKSPACE_STATE_WAITING`, `WORKSPACE_STATE_QUARANTINED`. diff --git a/src/content/docs/reference/security/known-gaps.md b/src/content/docs/reference/security/known-gaps.md index 48d98c3..6ee538c 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/b3598142dbcd6ef24135066332441a400dd35980/docs/security/README.md) at `b3598142d`. 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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/docs/security/README.md) at `4534f6521`. 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. diff --git a/src/content/docs/reference/security/rules.md b/src/content/docs/reference/security/rules.md index 2db656f..f1df9e6 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/b3598142dbcd6ef24135066332441a400dd35980/docs/security/README.md) at `b3598142d`. 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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/docs/security/README.md) at `4534f6521`. 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 | |---|---|---| diff --git a/src/content/docs/reference/status/index.md b/src/content/docs/reference/status/index.md index 045a2f6..235520d 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/b3598142dbcd6ef24135066332441a400dd35980/docs/ROADMAP.md). The page is written by `task reference` from `spin features` at spin `b3598142d`, and cannot say a feature the binary does not. +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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/docs/ROADMAP.md). The page is written by `task reference` from `spin features` at spin `4534f6521`, and cannot say a feature the binary does not. ## Built @@ -17,116 +17,116 @@ 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/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/vm_test.go#L167), a test of `internal/e2e` | [`TestAWorkspaceBootsARealGuest`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/vm_test.go#L167) | -| Create, start, stop and delete | [`WorkspaceService/CreateWorkspace`](/reference/api/workspaceservice/) | [`TestE2E_WorkspaceCRUD`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/cmd/cli/e2e_test.go#L397) | -| 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/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/background_test.go#L379), a test of `internal/e2e` | [`TestATrashedWorkspaceIsWholeWhenItsOwnerUndeletesIt`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/background_test.go#L411)
[`TestAWorkspaceWhoseDaysInTheTrashAreUpIsErasedFromItsHost`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/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/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/background_test.go#L107), a test of `internal/e2e` | [`TestAWorkspaceIsAskedBeforeItsSuspensionAndAKeepAnswersIt`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/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/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/background_test.go#L69), a test of `internal/e2e` | [`TestAWorkspaceThatRanForAsLongAsAllowedIsSuspended`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/background_test.go#L69) | -| A process inside holds its workspace awake while it lives | [`TestAProcessHoldsItsWorkspaceAwakeWhileItLives`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/background_test.go#L190), a test of `internal/e2e` | [`TestAProcessHoldsItsWorkspaceAwakeWhileItLives`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/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/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/background_test.go#L35), a test of `internal/e2e` | [`TestE2E_ASuspendedWorkspaceResumesWhereItWas`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/cmd/cli/journeys_e2e_test.go#L160)
[`TestAWorkspaceNobodyUsesIsSuspendedAndAStartResumesIt`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/background_test.go#L35) | -| Cores and memory lent while the host has them, and taken back | [`TestABusyWorkspaceIsLentCoresAndGivesThemBack`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/background_test.go#L342), a test of `internal/e2e` | not yet: memory lent and taken back, and a loan refused while the host is full | -| A grant of cores and memory of its own, for a while | [`TestAGrantWhoseTimeIsUpIsGivenBackToTheMachine`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/background_test.go#L288), a test of `internal/e2e` | [`TestAGrantWhoseTimeIsUpIsGivenBackToTheMachine`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/background_test.go#L288) | -| Move a running workspace to another host, its processes as they are | [`TestHostsAMoveTakesARunningWorkspaceToAnotherHost`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/hosts_flows_test.go#L65), a test of `internal/e2e` | [`TestHostsAMoveTakesARunningWorkspaceToAnotherHost`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/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/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/clone_test.go#L68), a test of `internal/e2e` | [`TestACloneHoldsWhatItsSourceWroteAndItsShape`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/clone_test.go#L68) | -| Recover a workspace whose host is gone, at a cost its owner accepts | [`TestHostsAWorkspaceWhoseHostIsGoneIsRecoveredOnAnother`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/hosts_flows_test.go#L99), a test of `internal/e2e` | not yet: the cost asked of the owner before a recovery, and what was written after the snapshot gone | -| A workspace outlives its runner | [`TestAWorkspaceOutlivesItsRunner`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/vm_test.go#L250), a test of `internal/e2e` | [`TestAWorkspaceOutlivesItsRunner`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/vm_test.go#L250) | -| Quarantine, by an administrator | [`WorkspaceService/QuarantineWorkspace`](/reference/api/workspaceservice/) | [`TestE2E_AQuarantinedWorkspaceIsHeldUntilReleased`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/cmd/cli/journeys_e2e_test.go#L209) | -| Why a workspace is not behaving: status, console, history | [`spin workspace status`](/reference/cli/workspace/) | [`TestE2E_AQuarantinedWorkspaceIsHeldUntilReleased`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/cmd/cli/journeys_e2e_test.go#L209)
[`TestE2E_AWorkspacesConsoleIsWhatItsMachinePrinted`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/cmd/cli/journeys_e2e_test.go#L243) | -| The owner's shell, environment, editor settings, Taskfile and dotfiles reach the guest | [`TestAWorkspacesOwnEnvironmentIsInItsOwnersLoginShell`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/env_test.go#L23), a test of `internal/e2e` | [`TestTheOwnersSettingsArriveInTheGuest`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/env_test.go#L64)
[`TestAWorkspacesOwnEnvironmentIsInItsOwnersLoginShell`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/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/b3598142dbcd6ef24135066332441a400dd35980/cmd/cli/e2e_test.go#L1182) | -| Claude Code and Codex on every workspace's PATH, at the versions the release pins, with their own defaults | [`TestTheAgentCLIsAreOnPathWithThePinnedVersions`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/agentclis_test.go#L20), a test of `internal/e2e` | [`TestTheAgentCLIsAreOnPathWithThePinnedVersions`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/agentclis_test.go#L20) | +| A machine per workspace: KVM, its own kernel, root, a persistent disk, SSH | [`TestAWorkspaceBootsARealGuest`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/vm_test.go#L167), a test of `internal/e2e` | [`TestAWorkspaceBootsARealGuest`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/vm_test.go#L167) | +| Create, start, stop and delete | [`WorkspaceService/CreateWorkspace`](/reference/api/workspaceservice/) | [`TestE2E_WorkspaceCRUD`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/cmd/cli/e2e_test.go#L397) | +| 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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/background_test.go#L379), a test of `internal/e2e` | [`TestATrashedWorkspaceIsWholeWhenItsOwnerUndeletesIt`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/background_test.go#L411)
[`TestAWorkspaceWhoseDaysInTheTrashAreUpIsErasedFromItsHost`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/background_test.go#L107), a test of `internal/e2e` | [`TestAWorkspaceIsAskedBeforeItsSuspensionAndAKeepAnswersIt`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/background_test.go#L69), a test of `internal/e2e` | [`TestAWorkspaceThatRanForAsLongAsAllowedIsSuspended`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/background_test.go#L69) | +| A process inside holds its workspace awake while it lives | [`TestAProcessHoldsItsWorkspaceAwakeWhileItLives`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/background_test.go#L190), a test of `internal/e2e` | [`TestAProcessHoldsItsWorkspaceAwakeWhileItLives`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/background_test.go#L35), a test of `internal/e2e` | [`TestE2E_ASuspendedWorkspaceResumesWhereItWas`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/cmd/cli/journeys_e2e_test.go#L160)
[`TestAWorkspaceNobodyUsesIsSuspendedAndAStartResumesIt`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/background_test.go#L35) | +| Cores and memory lent while the host has them, and taken back | [`TestABusyWorkspaceIsLentCoresAndGivesThemBack`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/background_test.go#L342), a test of `internal/e2e` | not yet: memory lent and taken back, and a loan refused while the host is full | +| A grant of cores and memory of its own, for a while | [`TestAGrantWhoseTimeIsUpIsGivenBackToTheMachine`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/background_test.go#L288), a test of `internal/e2e` | [`TestAGrantWhoseTimeIsUpIsGivenBackToTheMachine`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/background_test.go#L288) | +| Move a running workspace to another host, its processes as they are | [`TestHostsAMoveTakesARunningWorkspaceToAnotherHost`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/hosts_flows_test.go#L65), a test of `internal/e2e` | [`TestHostsAMoveTakesARunningWorkspaceToAnotherHost`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/clone_test.go#L68), a test of `internal/e2e` | [`TestACloneHoldsWhatItsSourceWroteAndItsShape`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/clone_test.go#L68) | +| Recover a workspace whose host is gone, at a cost its owner accepts | [`TestHostsAWorkspaceWhoseHostIsGoneIsRecoveredOnAnother`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/hosts_flows_test.go#L99), a test of `internal/e2e` | not yet: the cost asked of the owner before a recovery, and what was written after the snapshot gone | +| A workspace outlives its runner | [`TestAWorkspaceOutlivesItsRunner`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/vm_test.go#L250), a test of `internal/e2e` | [`TestAWorkspaceOutlivesItsRunner`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/vm_test.go#L250) | +| Quarantine, by an administrator | [`WorkspaceService/QuarantineWorkspace`](/reference/api/workspaceservice/) | [`TestE2E_AQuarantinedWorkspaceIsHeldUntilReleased`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/cmd/cli/journeys_e2e_test.go#L209) | +| Why a workspace is not behaving: status, console, history | [`spin workspace status`](/reference/cli/workspace/) | [`TestE2E_AQuarantinedWorkspaceIsHeldUntilReleased`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/cmd/cli/journeys_e2e_test.go#L209)
[`TestE2E_AWorkspacesConsoleIsWhatItsMachinePrinted`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/cmd/cli/journeys_e2e_test.go#L243) | +| The owner's shell, environment, editor settings, Taskfile and dotfiles reach the guest | [`TestAWorkspacesOwnEnvironmentIsInItsOwnersLoginShell`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/env_test.go#L23), a test of `internal/e2e` | [`TestTheOwnersSettingsArriveInTheGuest`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/env_test.go#L64)
[`TestAWorkspacesOwnEnvironmentIsInItsOwnersLoginShell`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/cmd/cli/e2e_test.go#L1182) | +| Claude Code and Codex on every workspace's PATH, at the versions the release pins, with their own defaults | [`TestTheAgentCLIsAreOnPathWithThePinnedVersions`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/agentclis_test.go#L20), a test of `internal/e2e` | [`TestTheAgentCLIsAreOnPathWithThePinnedVersions`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/agentclis_test.go#L20) | ### 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/b3598142dbcd6ef24135066332441a400dd35980/cmd/cli/journeys_e2e_test.go#L97) | -| A workspace opened at a commit or a pull request, checked out as pr-<n> | [`TestAProjectsWorkspaceOpensAtTheCommitItWasAskedFor`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/project_test.go#L91), a test of `internal/e2e` | [`TestAProjectsWorkspaceOpensAtTheCommitItWasAskedFor`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/project_test.go#L91)
[`TestE2E_AURLOpensTheWorkspaceItNames`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/cmd/cli/journeys_e2e_test.go#L97) | -| Teams, with owner, admin and member | [`spin team member role`](/reference/cli/team/) | [`TestE2E_ATeamRoleIsWhatItsHolderMayDo`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/cmd/cli/e2e_test.go#L473) | -| A team's own identity providers | [`TeamService/CreateIdentityProvider`](/reference/api/teamservice/) | [`TestE2E_ATeamsIdentityProviderIsItsAdminsAndSignsNobodyIn`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/cmd/cli/e2e_test.go#L505) | +| 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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/cmd/cli/journeys_e2e_test.go#L97) | +| A workspace opened at a commit or a pull request, checked out as pr-<n> | [`TestAProjectsWorkspaceOpensAtTheCommitItWasAskedFor`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/project_test.go#L91), a test of `internal/e2e` | [`TestAProjectsWorkspaceOpensAtTheCommitItWasAskedFor`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/project_test.go#L91)
[`TestE2E_AURLOpensTheWorkspaceItNames`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/cmd/cli/journeys_e2e_test.go#L97) | +| Teams, with owner, admin and member | [`spin team member role`](/reference/cli/team/) | [`TestE2E_ATeamRoleIsWhatItsHolderMayDo`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/cmd/cli/e2e_test.go#L473) | +| A team's own identity providers | [`TeamService/CreateIdentityProvider`](/reference/api/teamservice/) | [`TestE2E_ATeamsIdentityProviderIsItsAdminsAndSignsNobodyIn`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/cmd/cli/e2e_test.go#L505) | | A team's forge app: private repositories cloned and pushed with nothing on the disk | [`spin team forge set`](/reference/cli/team/) | not yet: a real GitHub App and a private repository for the lane to clone and push | -| 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/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/team_policy_test.go#L24) | -| Projects: a repository and the shape of the workspace that opens it | [`TestAProjectsWorkspaceHasItsRepositoryCheckedOutAtTheRef`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/project_test.go#L27), a test of `internal/e2e` | [`TestAProjectsWorkspaceHasItsRepositoryCheckedOutAtTheRef`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/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/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/prebuild_test.go#L29), a test of `internal/e2e` | [`TestAProjectOpensAsItsPrebuildMadeIt`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/prebuild_test.go#L29) | -| A team's workspaces run on the installation's hosts | [`TestATeamsWorkspaceRunsOnTheInstallationsHost`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/team_test.go#L20), a test of `internal/e2e` | [`TestATeamsWorkspaceRunsOnTheInstallationsHost`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/team_policy_test.go#L24) | +| Projects: a repository and the shape of the workspace that opens it | [`TestAProjectsWorkspaceHasItsRepositoryCheckedOutAtTheRef`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/project_test.go#L27), a test of `internal/e2e` | [`TestAProjectsWorkspaceHasItsRepositoryCheckedOutAtTheRef`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/prebuild_test.go#L29), a test of `internal/e2e` | [`TestAProjectOpensAsItsPrebuildMadeIt`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/prebuild_test.go#L29) | +| A team's workspaces run on the installation's hosts | [`TestATeamsWorkspaceRunsOnTheInstallationsHost`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/team_test.go#L20), a test of `internal/e2e` | [`TestATeamsWorkspaceRunsOnTheInstallationsHost`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/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/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/clone_test.go#L68)
[`TestADiskSnapshottedPastTheThresholdIsCompactedWhileItRuns`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/compaction_test.go#L19) | -| Snapshots with memory, resumed with their processes | [`TestARunningWorkspaceResumesFromASnapshotsMemory`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/restore_test.go#L175), a test of `internal/e2e` | [`TestARunningWorkspaceResumesFromASnapshotsMemory`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/restore_test.go#L175) | -| Restore a workspace to a snapshot | [`TestARestoredWorkspaceBootsOnTheSnapshotItWasRestoredTo`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/restore_test.go#L29), a test of `internal/e2e` | [`TestARestoredWorkspaceBootsOnTheSnapshotItWasRestoredTo`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/restore_test.go#L29) | -| A diff of the files that changed between two snapshots | [`TestADiffOfTwoSnapshotsIsWhatChangedBetweenThem`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/diff_test.go#L28), a test of `internal/e2e` | [`TestADiffOfTwoSnapshotsNamesWhatWasAddedChangedAndRemoved`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/diff_test.go#L95) | -| Share a snapshot with a person or make it public, and create a workspace from it | [`TestACloneOfASnapshotRegistersAsItself`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/clone_test.go#L24), a test of `internal/e2e` | [`TestASharedSnapshotIsCreatedFromByThePersonItIsSharedWith`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/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/b3598142dbcd6ef24135066332441a400dd35980/cmd/cli/journeys_e2e_test.go#L46) | -| A long chain is compacted while the workspace runs | [`TestADiskSnapshottedPastTheThresholdIsCompactedWhileItRuns`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/compaction_test.go#L19), a test of `internal/e2e` | [`TestADiskSnapshottedPastTheThresholdIsCompactedWhileItRuns`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/clone_test.go#L68)
[`TestADiskSnapshottedPastTheThresholdIsCompactedWhileItRuns`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/compaction_test.go#L19) | +| Snapshots with memory, resumed with their processes | [`TestARunningWorkspaceResumesFromASnapshotsMemory`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/restore_test.go#L175), a test of `internal/e2e` | [`TestARunningWorkspaceResumesFromASnapshotsMemory`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/restore_test.go#L175) | +| Restore a workspace to a snapshot | [`TestARestoredWorkspaceBootsOnTheSnapshotItWasRestoredTo`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/restore_test.go#L29), a test of `internal/e2e` | [`TestARestoredWorkspaceBootsOnTheSnapshotItWasRestoredTo`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/restore_test.go#L29) | +| A diff of the files that changed between two snapshots | [`TestADiffOfTwoSnapshotsIsWhatChangedBetweenThem`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/diff_test.go#L28), a test of `internal/e2e` | [`TestADiffOfTwoSnapshotsNamesWhatWasAddedChangedAndRemoved`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/diff_test.go#L95) | +| Share a snapshot with a person or make it public, and create a workspace from it | [`TestACloneOfASnapshotRegistersAsItself`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/clone_test.go#L24), a test of `internal/e2e` | [`TestASharedSnapshotIsCreatedFromByThePersonItIsSharedWith`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/cmd/cli/journeys_e2e_test.go#L46) | +| A long chain is compacted while the workspace runs | [`TestADiskSnapshottedPastTheThresholdIsCompactedWhileItRuns`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/compaction_test.go#L19), a test of `internal/e2e` | [`TestADiskSnapshottedPastTheThresholdIsCompactedWhileItRuns`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/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/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/retag_test.go#L163), a test of `internal/e2e` | [`TestAWorkspaceNamedNoPolicyReachesNothing`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/retag_test.go#L71)
[`TestChangingAWorkspacesPoliciesReachesTheHostThatRunsIt`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/retag_test.go#L24) | -| A policy changed reaches the host that runs the workspace | [`TestChangingAWorkspacesPoliciesReachesTheHostThatRunsIt`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/retag_test.go#L24), a test of `internal/e2e` | [`TestAnEditedPolicyChangesWhatARunningGuestReaches`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/retag_test.go#L100)
[`TestChangingAWorkspacesPoliciesReachesTheHostThatRunsIt`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/retag_test.go#L24) | +| Egress is closed by default; policies, by tag, name what a workspace may reach | [`TestAnOwnerMayOnlyChooseAPolicyTheInstallationDeclares`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/retag_test.go#L163), a test of `internal/e2e` | [`TestAWorkspaceNamedNoPolicyReachesNothing`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/retag_test.go#L71)
[`TestChangingAWorkspacesPoliciesReachesTheHostThatRunsIt`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/retag_test.go#L24) | +| A policy changed reaches the host that runs the workspace | [`TestChangingAWorkspacesPoliciesReachesTheHostThatRunsIt`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/retag_test.go#L24), a test of `internal/e2e` | [`TestAnEditedPolicyChangesWhatARunningGuestReaches`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/retag_test.go#L100)
[`TestChangingAWorkspacesPoliciesReachesTheHostThatRunsIt`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/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 | [`spin team secret set`](/reference/cli/team/) | not yet: the forge, identity and cloud role injections, and the secret's value seen at the origin | -| A workspace trusts the egress root only by its owner's word | [`TestAGuestTrustsTheEgressRootOnlyByItsOwnersWord`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/egress_root_test.go#L20), a test of `internal/e2e` | [`TestAGuestTrustsTheEgressRootOnlyByItsOwnersWord`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/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/b3598142dbcd6ef24135066332441a400dd35980/cmd/cli/e2e_test.go#L766) | -| 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/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/brokered_test.go#L28), a test of `internal/e2e` | [`TestABrokeredRequestIsSeenAsTheProxyReadIt`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/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/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/egress_process_test.go#L21), a test of `internal/e2e` | [`TestTheEgressProxyIsAProcessOfItsOwnThatTheRunnerStartsAgain`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/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/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/brokered_test.go#L72), a test of `internal/e2e` | [`TestAPersonsRuleAndAnAgentsOnOneNameEachArriveWithTheirOwnInjection`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/brokered_test.go#L100)
[`TestABrokeredNameForTheAgentIsTheAgentsAlone`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/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/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/brokered_test.go#L168), a test of `internal/e2e` | [`TestAWebSocketToABrokeredNameCarriesTheGuestsBytesAndRefusesAPathOutOfScope`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/brokered_test.go#L196)
[`TestAWebSocketToABrokeredNameIsCarriedAfterItsHandshake`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/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 | [`TestHTTP2ToABrokeredNameIsTheRealHosts`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/brokered_test.go#L231), a test of `internal/e2e` | not yet: headers on several streams and gRPC's trailers, which need an h2 origin that echoes them | -| Watch where a workspace connects, into its logs | [`spin workspace watch`](/reference/cli/workspace/) | [`TestE2E_AWatchedWorkspacesConnectionsAreInItsLogs`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/cmd/cli/journeys_e2e_test.go#L264) | -| An agent the supervisor starts is marked, and reaches only brokered names | [`TestARealWorkspaceMarksTheAgentItsSupervisorStarts`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/seal_test.go#L21), a test of `internal/e2e` | [`TestAnAgentReachesOnlyBrokeredNames`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/brokered_test.go#L138)
[`TestARealWorkspaceMarksTheAgentItsSupervisorStarts`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/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/b3598142dbcd6ef24135066332441a400dd35980/cmd/proxy/lane_test.go#L144)
[`workspace-sign-in.spec.ts`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/dashboard/e2e/workspace-sign-in.spec.ts#L31): a visitor signed in to the dashboard reaches their private port | +| A workspace trusts the egress root only by its owner's word | [`TestAGuestTrustsTheEgressRootOnlyByItsOwnersWord`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/egress_root_test.go#L20), a test of `internal/e2e` | [`TestAGuestTrustsTheEgressRootOnlyByItsOwnersWord`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/cmd/cli/e2e_test.go#L766) | +| 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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/brokered_test.go#L28), a test of `internal/e2e` | [`TestABrokeredRequestIsSeenAsTheProxyReadIt`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/egress_process_test.go#L21), a test of `internal/e2e` | [`TestTheEgressProxyIsAProcessOfItsOwnThatTheRunnerStartsAgain`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/brokered_test.go#L72), a test of `internal/e2e` | [`TestAPersonsRuleAndAnAgentsOnOneNameEachArriveWithTheirOwnInjection`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/brokered_test.go#L100)
[`TestABrokeredNameForTheAgentIsTheAgentsAlone`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/brokered_test.go#L168), a test of `internal/e2e` | [`TestAWebSocketToABrokeredNameCarriesTheGuestsBytesAndRefusesAPathOutOfScope`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/brokered_test.go#L196)
[`TestAWebSocketToABrokeredNameIsCarriedAfterItsHandshake`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/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 | [`TestHTTP2ToABrokeredNameIsTheRealHosts`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/brokered_test.go#L231), a test of `internal/e2e` | not yet: headers on several streams and gRPC's trailers, which need an h2 origin that echoes them | +| Watch where a workspace connects, into its logs | [`spin workspace watch`](/reference/cli/workspace/) | [`TestE2E_AWatchedWorkspacesConnectionsAreInItsLogs`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/cmd/cli/journeys_e2e_test.go#L264) | +| An agent the supervisor starts is marked, and reaches only brokered names | [`TestARealWorkspaceMarksTheAgentItsSupervisorStarts`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/seal_test.go#L21), a test of `internal/e2e` | [`TestAnAgentReachesOnlyBrokeredNames`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/brokered_test.go#L138)
[`TestARealWorkspaceMarksTheAgentItsSupervisorStarts`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/cmd/proxy/lane_test.go#L144)
[`workspace-sign-in.spec.ts`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/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/b3598142dbcd6ef24135066332441a400dd35980/cmd/cli/e2e_test.go#L1169)
[`auth.spec.ts`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/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/b3598142dbcd6ef24135066332441a400dd35980/cmd/cli/e2e_test.go#L1124) | -| SSH keys, and plain ssh to spin.<workspace> | [`spin ssh-config`](/reference/cli/ssh-config/) | [`TestE2E_SSHConfigCarriesSSHToAWorkspace`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/cmd/cli/e2e_test.go#L637) | -| Who logs in to a workspace is what its owner signed | [`TestOnlyThePeopleTheAccessNamesLogInToAWorkspace`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/login_test.go#L259), a test of `internal/e2e` | [`TestOnlyThePeopleTheAccessNamesLogInToAWorkspace`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/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/b3598142dbcd6ef24135066332441a400dd35980/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/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/identity_test.go#L60), a test of `internal/e2e` | [`TestAWorkspacesIdentityIsTheHostsSignatureOfWhatItsOwnerSigned`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/identity_test.go#L60) | -| VS Code over SSH, with the server the installation publishes and nothing downloaded
*spin code itself is run by its unit tests only: it opens VS Code desktop, which no lane has.* | [`TestAVSCodeServerOfAnotherCommitIsHandedToTheRunningMachine`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/vscodehotplug_test.go#L23), a test of `internal/e2e` | [`TestTheCarriedVSCodeServerRunsOfflineAndAnswersOverTheSSHTunnel`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/vscodeserver_test.go#L86)
[`TestAVSCodeServerOfAnotherCommitIsHandedToTheRunningMachine`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/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/b3598142dbcd6ef24135066332441a400dd35980/cmd/cli/journeys_e2e_test.go#L178) | +| Device login for a terminal | [`AuthService/StartDeviceLogin`](/reference/api/authservice/) | [`TestE2E_Logout`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/cmd/cli/e2e_test.go#L1169)
[`auth.spec.ts`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/cmd/cli/e2e_test.go#L1124) | +| SSH keys, and plain ssh to spin.<workspace> | [`spin ssh-config`](/reference/cli/ssh-config/) | [`TestE2E_SSHConfigCarriesSSHToAWorkspace`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/cmd/cli/e2e_test.go#L637) | +| Who logs in to a workspace is what its owner signed | [`TestOnlyThePeopleTheAccessNamesLogInToAWorkspace`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/login_test.go#L259), a test of `internal/e2e` | [`TestOnlyThePeopleTheAccessNamesLogInToAWorkspace`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/identity_test.go#L60), a test of `internal/e2e` | [`TestAWorkspacesIdentityIsTheHostsSignatureOfWhatItsOwnerSigned`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/identity_test.go#L60) | +| VS Code over SSH, with the server the installation publishes and nothing downloaded
*spin code itself is run by its unit tests only: it opens VS Code desktop, which no lane has.* | [`TestAVSCodeServerOfAnotherCommitIsHandedToTheRunningMachine`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/vscodehotplug_test.go#L23), a test of `internal/e2e` | [`TestTheCarriedVSCodeServerRunsOfflineAndAnswersOverTheSSHTunnel`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/vscodeserver_test.go#L86)
[`TestAVSCodeServerOfAnotherCommitIsHandedToTheRunningMachine`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/cmd/cli/journeys_e2e_test.go#L178) | ### 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/) | not yet: the real file read, an apply and its effect, and a dismiss kept when the file is read again | -| Resource presets | [`AdminService/CreateResourcePreset`](/reference/api/adminservice/) | [`admin.spec.ts`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/dashboard/e2e/admin.spec.ts#L422): 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/b3598142dbcd6ef24135066332441a400dd35980/dashboard/e2e/admin.spec.ts#L216): closed, open and a domain on the allowlist decide who registers
[`admin.spec.ts`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/dashboard/e2e/admin.spec.ts#L146): 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/b3598142dbcd6ef24135066332441a400dd35980/cmd/cli/e2e_test.go#L580)
[`admin.spec.ts`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/dashboard/e2e/admin.spec.ts#L895): 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/) | [`TestACarryResumesASuspendedWorkspaceAndStopsIt`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/carry_test.go#L21)
[`admin.spec.ts`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/dashboard/e2e/admin.spec.ts#L705): admin runs a job by hand and sees how it ended | +| Resource presets | [`AdminService/CreateResourcePreset`](/reference/api/adminservice/) | [`admin.spec.ts`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/dashboard/e2e/admin.spec.ts#L422): 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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/dashboard/e2e/admin.spec.ts#L216): closed, open and a domain on the allowlist decide who registers
[`admin.spec.ts`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/dashboard/e2e/admin.spec.ts#L146): 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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/cmd/cli/e2e_test.go#L580)
[`admin.spec.ts`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/dashboard/e2e/admin.spec.ts#L895): 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/) | [`TestACarryResumesASuspendedWorkspaceAndStopsIt`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/carry_test.go#L21)
[`admin.spec.ts`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/dashboard/e2e/admin.spec.ts#L705): 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/b3598142dbcd6ef24135066332441a400dd35980/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/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/rekey_test.go#L24) | +| 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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/rekey_test.go#L24) | | Runners: registration tokens, drain, activate, revoke, and a policy per host | [`spin admin runner drain`](/reference/cli/admin/) | not yet: a runner registered with a token the API made, an expired or revoked token refused, and a revoke carried out | | 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 host that reboots brings its workspaces back | [`TestAHostRebootBringsItsWorkspacesBack`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/restart_test.go#L38), a test of `internal/e2e` | [`TestAHostRebootBringsItsWorkspacesBack`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/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/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/preemption_test.go#L26), a test of `internal/e2e` | [`TestACloudsReclaimWarningEmptiesTheHostBeforeAnySignal`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/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/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/writeback_test.go#L28), a test of `internal/e2e` | [`TestCustomWritebackValuesAreMeasuredOnTheRunner`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/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/b3598142dbcd6ef24135066332441a400dd35980/cmd/cli/e2e_test.go#L1026) | +| A host that reboots brings its workspaces back | [`TestAHostRebootBringsItsWorkspacesBack`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/restart_test.go#L38), a test of `internal/e2e` | [`TestAHostRebootBringsItsWorkspacesBack`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/preemption_test.go#L26), a test of `internal/e2e` | [`TestACloudsReclaimWarningEmptiesTheHostBeforeAnySignal`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/writeback_test.go#L28), a test of `internal/e2e` | [`TestCustomWritebackValuesAreMeasuredOnTheRunner`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/cmd/cli/e2e_test.go#L1026) | ### 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/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/observe_test.go#L22)
[`TestE2E_TheInstallationsLogsAreSearchable`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/cmd/cli/e2e_test.go#L928) | -| Metrics, with Grafana on the control plane | [`AdminService/GetMonitoring`](/reference/api/adminservice/) | [`admin.spec.ts`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/dashboard/e2e/admin.spec.ts#L1149): 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/b3598142dbcd6ef24135066332441a400dd35980/dashboard/e2e/admin.spec.ts#L1126): 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/b3598142dbcd6ef24135066332441a400dd35980/cmd/cli/e2e_test.go#L949) | +| Platform logs, workspace logs and traces, searched in the product | [`LogService/SearchPlatformLogs`](/reference/api/logservice/) | [`TestAWorkspacesLinesAndTracesAreFoundBySearchingForIt`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/observe_test.go#L22)
[`TestE2E_TheInstallationsLogsAreSearchable`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/cmd/cli/e2e_test.go#L928) | +| Metrics, with Grafana on the control plane | [`AdminService/GetMonitoring`](/reference/api/adminservice/) | [`admin.spec.ts`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/dashboard/e2e/admin.spec.ts#L1149): 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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/dashboard/e2e/admin.spec.ts#L1126): 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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/cmd/cli/e2e_test.go#L949) | ### 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/b3598142dbcd6ef24135066332441a400dd35980/cmd/cli/journeys_e2e_test.go#L314) | -| 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/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/suspend_test.go#L126), a test of `internal/e2e` | [`TestAMachineAdoptedWithoutItsReleasesIsSuspendedWithItsDisk`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/internal/e2e/suspend_test.go#L126)
[`TestAVSCodeServerOfAnotherCommitIsHandedToTheRunningMachine`](https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/cmd/cli/journeys_e2e_test.go#L314) | +| 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/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/suspend_test.go#L126), a test of `internal/e2e` | [`TestAMachineAdoptedWithoutItsReleasesIsSuspendedWithItsDisk`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/internal/e2e/suspend_test.go#L126)
[`TestAVSCodeServerOfAnotherCommitIsHandedToTheRunningMachine`](https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/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 bb25b14..733fdf1 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 v20261024.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 v20261025.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/figures.json b/src/data/figures.json index df1cec1..0a318bf 100644 --- a/src/data/figures.json +++ b/src/data/figures.json @@ -1,6 +1,6 @@ { "datapath": { - "source": "https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/docs/network/datapath", + "source": "https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/docs/network/datapath", "width": 552, "words": [ "How a packet leaves a workspace", @@ -56,7 +56,7 @@ ] }, "egress-policy": { - "source": "https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/docs/network/egress-policy", + "source": "https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/docs/network/egress-policy", "width": 854, "words": [ "What the forward chain decides, in order", @@ -157,7 +157,7 @@ ] }, "isolation": { - "source": "https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/docs/network/isolation", + "source": "https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/docs/network/isolation", "width": 499, "words": [ "Same address, different segment", @@ -204,7 +204,7 @@ ] }, "traffic": { - "source": "https://github.com/spin-stack/spin/blob/b3598142dbcd6ef24135066332441a400dd35980/docs/security/traffic", + "source": "https://github.com/spin-stack/spin/blob/4534f652122fbb0bb2ba8e434f6e4cd73212fa18/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/reference.json b/src/data/reference.json index 1858255..3543250 100644 --- a/src/data/reference.json +++ b/src/data/reference.json @@ -1,8 +1,8 @@ { "spin": { "installs": "v20261019.02", - "commit": "b3598142dbcd6ef24135066332441a400dd35980", - "tag": "v20261024.01", + "commit": "4534f652122fbb0bb2ba8e434f6e4cd73212fa18", + "tag": "v20261025.01", "machine": "v20261014.01" }, "terraform": { @@ -10,7 +10,7 @@ "release": "v20261024.01" }, "brand": { - "commit": "c882b6f0f3901787525ef16ef29058c9c1418cbe" + "commit": "31d07eb9b76596695a138ff96403d881f358e80d" }, "counts": { "built": 75, @@ -20,5 +20,5 @@ "endToEnd": 65, "gap": 10 }, - "openapiSha256": "f600ebac2a39e1b1e59bcb3b08ebfd80692432d8d98b29111b55991729f924d2" + "openapiSha256": "55f225492362049f6ed1501104de85e6345aa55a6163f0aa0bf96950aff45322" } diff --git a/src/data/shots.json b/src/data/shots.json index f2be707..ccd27ff 100644 --- a/src/data/shots.json +++ b/src/data/shots.json @@ -1,6 +1,6 @@ { - "release": "v20261024.01", - "commit": "b3598142dbcd6ef24135066332441a400dd35980", + "release": "v20261025.01", + "commit": "4534f652122fbb0bb2ba8e434f6e4cd73212fa18", "shots": [ { "name": "workspaces", diff --git a/versions.yaml b/versions.yaml index 39dcf2d..a7d6958 100644 --- a/versions.yaml +++ b/versions.yaml @@ -7,8 +7,8 @@ - name: spin kind: git source: https://github.com/spin-stack/spin - version: v20261024.01 - pin: b3598142dbcd6ef24135066332441a400dd35980 + version: v20261025.01 + pin: 4534f652122fbb0bb2ba8e434f6e4cd73212fa18 track: github-release note: >- The release the site documents (D2: the newest, exactly). The daily sync moves it to the next @@ -29,7 +29,7 @@ kind: git source: https://github.com/spin-stack/brand version: main - pin: c882b6f0f3901787525ef16ef29058c9c1418cbe + pin: 31d07eb9b76596695a138ff96403d881f358e80d track: branch note: >- The palette and the logos. brand cuts no releases, so its main is what it has to say. The