diff --git a/src/assets/shots/workspace.png b/src/assets/shots/workspace.png
index a07e0aa..4bb29bd 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 bd8afb7..f2c34ef 100644
Binary files a/src/assets/shots/workspaces.png and b/src/assets/shots/workspaces.png differ
diff --git a/src/content/docs/reference/security/known-gaps.md b/src/content/docs/reference/security/known-gaps.md
index 381abb5..64fe38e 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/55e6962b058f3d27f94255704b1ab96250a32de2/docs/security/README.md) at `55e6962b0`. 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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/docs/security/README.md) at `c02ffc3ac`. 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 2a3f73e..f2495e4 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/55e6962b058f3d27f94255704b1ab96250a32de2/docs/security/README.md) at `55e6962b0`. 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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/docs/security/README.md) at `c02ffc3ac`. 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 2d40675..44cd56d 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/55e6962b058f3d27f94255704b1ab96250a32de2/docs/ROADMAP.md). The page is written by `task reference` from `spin features` at spin `55e6962b0`, 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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/docs/ROADMAP.md). The page is written by `task reference` from `spin features` at spin `c02ffc3ac`, 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/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/vm_test.go#L189), a test of `internal/e2e` | [`TestAWorkspaceBootsARealGuest`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/vm_test.go#L189) |
-| Create, start, stop and delete | [`WorkspaceService/CreateWorkspace`](/reference/api/workspaceservice/) | [`TestE2E_WorkspaceCRUD`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/cmd/cli/e2e_test.go#L423) |
-| 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/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/background_test.go#L379), a test of `internal/e2e` | [`TestATrashedWorkspaceIsWholeWhenItsOwnerUndeletesIt`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/background_test.go#L411)
[`TestAWorkspaceWhoseDaysInTheTrashAreUpIsErasedFromItsHost`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/background_test.go#L107), a test of `internal/e2e` | [`TestAWorkspaceIsAskedBeforeItsSuspensionAndAKeepAnswersIt`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/background_test.go#L69), a test of `internal/e2e` | [`TestAWorkspaceThatRanForAsLongAsAllowedIsSuspended`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/background_test.go#L69) |
-| A process inside holds its workspace awake while it lives | [`TestAProcessHoldsItsWorkspaceAwakeWhileItLives`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/background_test.go#L190), a test of `internal/e2e` | [`TestAProcessHoldsItsWorkspaceAwakeWhileItLives`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/background_test.go#L35), a test of `internal/e2e` | [`TestE2E_ASuspendedWorkspaceResumesWhereItWas`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/cmd/cli/journeys_e2e_test.go#L160)
[`TestAWorkspaceNobodyUsesIsSuspendedAndAStartResumesIt`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/background_test.go#L35) |
-| Cores and memory lent while the host has them, and taken back
*A loan refused while the host is full has no test against the stack: the budget is the host's own cores and half its memory, which no lane's workspaces fill.* | [`TestABusyWorkspaceIsLentCoresAndGivesThemBack`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/background_test.go#L342), a test of `internal/e2e` | [`TestABusyWorkspaceIsLentCoresAndGivesThemBack`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/background_test.go#L342)
[`TestABusyWorkspaceIsLentMemoryAndGivesItBack`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/memory_test.go#L109) |
-| A grant of cores and memory of its own, for a while | [`TestAGrantWhoseTimeIsUpIsGivenBackToTheMachine`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/background_test.go#L288), a test of `internal/e2e` | [`TestAGrantWhoseTimeIsUpIsGivenBackToTheMachine`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/hosts_flows_test.go#L65), a test of `internal/e2e` | [`TestHostsAMoveTakesARunningWorkspaceToAnotherHost`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/clone_test.go#L64), a test of `internal/e2e` | [`TestACloneHoldsWhatItsSourceWroteAndItsShape`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/clone_test.go#L64) |
-| Recover a workspace whose host is gone, at a cost its owner accepts | [`TestHostsAWorkspaceWhoseHostIsGoneIsRecoveredOnAnother`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/hosts_flows_test.go#L100), a test of `internal/e2e` | [`TestHostsAWorkspaceWhoseHostIsGoneIsRecoveredOnAnother`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/hosts_flows_test.go#L100) |
-| A workspace outlives its runner | [`TestAWorkspaceOutlivesItsRunner`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/vm_test.go#L272), a test of `internal/e2e` | [`TestAWorkspaceOutlivesItsRunner`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/vm_test.go#L272) |
-| Quarantine, by an administrator | [`WorkspaceService/QuarantineWorkspace`](/reference/api/workspaceservice/) | [`TestE2E_AQuarantinedWorkspaceIsHeldUntilReleased`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/cmd/cli/journeys_e2e_test.go#L209)
[`TestE2E_AWorkspacesConsoleIsWhatItsMachinePrinted`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/env_test.go#L23), a test of `internal/e2e` | [`TestTheOwnersSettingsArriveInTheGuest`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/env_test.go#L64)
[`TestAWorkspacesOwnEnvironmentIsInItsOwnersLoginShell`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/cmd/cli/e2e_test.go#L1208) |
-| Claude Code and Codex on every workspace's PATH, at the versions the release pins, with their own defaults
*Where the installation fetches them (agents_fetch) or an operator publishes them: no image carries Claude Code, which only Anthropic may distribute.* | [`TestTheAgentCLIsAreOnPathWithThePinnedVersions`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/agentclis_test.go#L20), a test of `internal/e2e` | [`TestTheAgentCLIsAreOnPathWithThePinnedVersions`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/vm_test.go#L189), a test of `internal/e2e` | [`TestAWorkspaceBootsARealGuest`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/vm_test.go#L189) |
+| Create, start, stop and delete | [`WorkspaceService/CreateWorkspace`](/reference/api/workspaceservice/) | [`TestE2E_WorkspaceCRUD`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/cmd/cli/e2e_test.go#L423) |
+| 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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/background_test.go#L379), a test of `internal/e2e` | [`TestATrashedWorkspaceIsWholeWhenItsOwnerUndeletesIt`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/background_test.go#L411)
[`TestAWorkspaceWhoseDaysInTheTrashAreUpIsErasedFromItsHost`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/background_test.go#L107), a test of `internal/e2e` | [`TestAWorkspaceIsAskedBeforeItsSuspensionAndAKeepAnswersIt`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/background_test.go#L69), a test of `internal/e2e` | [`TestAWorkspaceThatRanForAsLongAsAllowedIsSuspended`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/background_test.go#L69) |
+| A process inside holds its workspace awake while it lives | [`TestAProcessHoldsItsWorkspaceAwakeWhileItLives`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/background_test.go#L190), a test of `internal/e2e` | [`TestAProcessHoldsItsWorkspaceAwakeWhileItLives`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/background_test.go#L35), a test of `internal/e2e` | [`TestE2E_ASuspendedWorkspaceResumesWhereItWas`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/cmd/cli/journeys_e2e_test.go#L160)
[`TestAWorkspaceNobodyUsesIsSuspendedAndAStartResumesIt`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/background_test.go#L35) |
+| Cores and memory lent while the host has them, and taken back
*A loan refused while the host is full has no test against the stack: the budget is the host's own cores and half its memory, which no lane's workspaces fill.* | [`TestABusyWorkspaceIsLentCoresAndGivesThemBack`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/background_test.go#L342), a test of `internal/e2e` | [`TestABusyWorkspaceIsLentCoresAndGivesThemBack`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/background_test.go#L342)
[`TestABusyWorkspaceIsLentMemoryAndGivesItBack`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/memory_test.go#L109) |
+| A grant of cores and memory of its own, for a while | [`TestAGrantWhoseTimeIsUpIsGivenBackToTheMachine`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/background_test.go#L288), a test of `internal/e2e` | [`TestAGrantWhoseTimeIsUpIsGivenBackToTheMachine`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/hosts_flows_test.go#L65), a test of `internal/e2e` | [`TestHostsAMoveTakesARunningWorkspaceToAnotherHost`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/clone_test.go#L64), a test of `internal/e2e` | [`TestACloneHoldsWhatItsSourceWroteAndItsShape`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/clone_test.go#L64) |
+| Recover a workspace whose host is gone, at a cost its owner accepts | [`TestHostsAWorkspaceWhoseHostIsGoneIsRecoveredOnAnother`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/hosts_flows_test.go#L100), a test of `internal/e2e` | [`TestHostsAWorkspaceWhoseHostIsGoneIsRecoveredOnAnother`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/hosts_flows_test.go#L100) |
+| A workspace outlives its runner | [`TestAWorkspaceOutlivesItsRunner`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/vm_test.go#L272), a test of `internal/e2e` | [`TestAWorkspaceOutlivesItsRunner`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/vm_test.go#L272) |
+| Quarantine, by an administrator | [`WorkspaceService/QuarantineWorkspace`](/reference/api/workspaceservice/) | [`TestE2E_AQuarantinedWorkspaceIsHeldUntilReleased`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/cmd/cli/journeys_e2e_test.go#L209)
[`TestE2E_AWorkspacesConsoleIsWhatItsMachinePrinted`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/env_test.go#L23), a test of `internal/e2e` | [`TestTheOwnersSettingsArriveInTheGuest`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/env_test.go#L64)
[`TestAWorkspacesOwnEnvironmentIsInItsOwnersLoginShell`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/cmd/cli/e2e_test.go#L1208) |
+| Claude Code and Codex on every workspace's PATH, at the versions the release pins, with their own defaults
*Where the installation fetches them (agents_fetch) or an operator publishes them: no image carries Claude Code, which only Anthropic may distribute.* | [`TestTheAgentCLIsAreOnPathWithThePinnedVersions`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/agentclis_test.go#L20), a test of `internal/e2e` | [`TestTheAgentCLIsAreOnPathWithThePinnedVersions`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/project_test.go#L91), a test of `internal/e2e` | [`TestAProjectsWorkspaceOpensAtTheCommitItWasAskedFor`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/project_test.go#L91)
[`TestE2E_AURLOpensTheWorkspaceItNames`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/cmd/cli/e2e_test.go#L499) |
-| A team's own identity providers | [`TeamService/CreateIdentityProvider`](/reference/api/teamservice/) | [`TestE2E_ATeamsIdentityProviderIsItsAdminsAndSignsNobodyIn`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/cmd/cli/e2e_test.go#L531) |
+| 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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/project_test.go#L91), a test of `internal/e2e` | [`TestAProjectsWorkspaceOpensAtTheCommitItWasAskedFor`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/project_test.go#L91)
[`TestE2E_AURLOpensTheWorkspaceItNames`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/cmd/cli/e2e_test.go#L499) |
+| A team's own identity providers | [`TeamService/CreateIdentityProvider`](/reference/api/teamservice/) | [`TestE2E_ATeamsIdentityProviderIsItsAdminsAndSignsNobodyIn`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/cmd/cli/e2e_test.go#L531) |
| 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/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/project_test.go#L27), a test of `internal/e2e` | [`TestAProjectsWorkspaceHasItsRepositoryCheckedOutAtTheRef`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/prebuild_test.go#L29), a test of `internal/e2e` | [`TestAProjectOpensAsItsPrebuildMadeIt`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/prebuild_test.go#L29) |
-| A team's workspaces run on the installation's hosts | [`TestATeamsWorkspaceRunsOnTheInstallationsHost`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/team_test.go#L20), a test of `internal/e2e` | [`TestATeamsWorkspaceRunsOnTheInstallationsHost`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/project_test.go#L27), a test of `internal/e2e` | [`TestAProjectsWorkspaceHasItsRepositoryCheckedOutAtTheRef`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/prebuild_test.go#L29), a test of `internal/e2e` | [`TestAProjectOpensAsItsPrebuildMadeIt`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/prebuild_test.go#L29) |
+| A team's workspaces run on the installation's hosts | [`TestATeamsWorkspaceRunsOnTheInstallationsHost`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/team_test.go#L20), a test of `internal/e2e` | [`TestATeamsWorkspaceRunsOnTheInstallationsHost`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/clone_test.go#L64)
[`TestADiskSnapshottedPastTheThresholdIsCompactedWhileItRuns`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/compaction_test.go#L19) |
-| Snapshots with memory, resumed with their processes | [`TestARunningWorkspaceResumesFromASnapshotsMemory`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/restore_test.go#L175), a test of `internal/e2e` | [`TestARunningWorkspaceResumesFromASnapshotsMemory`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/restore_test.go#L175) |
-| Restore a workspace to a snapshot | [`TestARestoredWorkspaceBootsOnTheSnapshotItWasRestoredTo`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/restore_test.go#L29), a test of `internal/e2e` | [`TestARestoredWorkspaceBootsOnTheSnapshotItWasRestoredTo`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/restore_test.go#L29) |
-| A diff of the files that changed between two snapshots | [`TestADiffOfTwoSnapshotsIsWhatChangedBetweenThem`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/diff_test.go#L28), a test of `internal/e2e` | [`TestADiffOfTwoSnapshotsNamesWhatWasAddedChangedAndRemoved`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/clone_test.go#L24), a test of `internal/e2e` | [`TestASharedSnapshotIsCreatedFromByThePersonItIsSharedWith`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/cmd/cli/journeys_e2e_test.go#L46) |
-| A long chain is compacted while the workspace runs | [`TestADiskSnapshottedPastTheThresholdIsCompactedWhileItRuns`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/compaction_test.go#L19), a test of `internal/e2e` | [`TestADiskSnapshottedPastTheThresholdIsCompactedWhileItRuns`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/clone_test.go#L64)
[`TestADiskSnapshottedPastTheThresholdIsCompactedWhileItRuns`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/compaction_test.go#L19) |
+| Snapshots with memory, resumed with their processes | [`TestARunningWorkspaceResumesFromASnapshotsMemory`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/restore_test.go#L175), a test of `internal/e2e` | [`TestARunningWorkspaceResumesFromASnapshotsMemory`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/restore_test.go#L175) |
+| Restore a workspace to a snapshot | [`TestARestoredWorkspaceBootsOnTheSnapshotItWasRestoredTo`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/restore_test.go#L29), a test of `internal/e2e` | [`TestARestoredWorkspaceBootsOnTheSnapshotItWasRestoredTo`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/restore_test.go#L29) |
+| A diff of the files that changed between two snapshots | [`TestADiffOfTwoSnapshotsIsWhatChangedBetweenThem`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/diff_test.go#L28), a test of `internal/e2e` | [`TestADiffOfTwoSnapshotsNamesWhatWasAddedChangedAndRemoved`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/clone_test.go#L24), a test of `internal/e2e` | [`TestASharedSnapshotIsCreatedFromByThePersonItIsSharedWith`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/cmd/cli/journeys_e2e_test.go#L46) |
+| A long chain is compacted while the workspace runs | [`TestADiskSnapshottedPastTheThresholdIsCompactedWhileItRuns`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/compaction_test.go#L19), a test of `internal/e2e` | [`TestADiskSnapshottedPastTheThresholdIsCompactedWhileItRuns`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/retag_test.go#L163), a test of `internal/e2e` | [`TestAWorkspaceNamedNoPolicyReachesNothing`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/retag_test.go#L71)
[`TestChangingAWorkspacesPoliciesReachesTheHostThatRunsIt`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/retag_test.go#L24) |
-| A policy changed reaches the host that runs the workspace | [`TestChangingAWorkspacesPoliciesReachesTheHostThatRunsIt`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/retag_test.go#L24), a test of `internal/e2e` | [`TestAnEditedPolicyChangesWhatARunningGuestReaches`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/retag_test.go#L100)
[`TestChangingAWorkspacesPoliciesReachesTheHostThatRunsIt`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/retag_test.go#L24) |
-| Brokered names: the host's proxy stands in and adds what the workspace never holds - a team secret, a forge token, its identity, a cloud role
*The team secret's value is read at the origin; the forge token, identity and cloud role injections have no test against the stack.* | [`spin team secret set`](/reference/cli/team/) | [`TestAPersonsRuleAndAnAgentsOnOneNameEachArriveWithTheirOwnInjection`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/brokered_test.go#L100) |
-| A workspace trusts the egress root only by its owner's word | [`TestAGuestTrustsTheEgressRootOnlyByItsOwnersWord`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/egress_root_test.go#L20), a test of `internal/e2e` | [`TestAGuestTrustsTheEgressRootOnlyByItsOwnersWord`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/cmd/cli/e2e_test.go#L792) |
-| 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/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/brokered_test.go#L28), a test of `internal/e2e` | [`TestABrokeredRequestIsSeenAsTheProxyReadIt`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/egress_process_test.go#L21), a test of `internal/e2e` | [`TestTheEgressProxyIsAProcessOfItsOwnThatTheRunnerStartsAgain`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/brokered_test.go#L72), a test of `internal/e2e` | [`TestAPersonsRuleAndAnAgentsOnOneNameEachArriveWithTheirOwnInjection`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/brokered_test.go#L100)
[`TestABrokeredNameForTheAgentIsTheAgentsAlone`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/brokered_test.go#L168), a test of `internal/e2e` | [`TestAWebSocketToABrokeredNameCarriesTheGuestsBytesAndRefusesAPathOutOfScope`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/brokered_test.go#L196)
[`TestAWebSocketToABrokeredNameIsCarriedAfterItsHandshake`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/brokered_test.go#L168) |
-| HTTP/2 to a brokered name, the proxy's ALPN the real host's: a rule's headers set stream by stream, gRPC's trailers both ways
*gRPC's trailers are egressproxy's h2 test against an origin of its own; the lane has no gRPC origin to reach.* | [`TestHTTP2ToABrokeredNameIsTheRealHosts`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/brokered_test.go#L231), a test of `internal/e2e` | [`TestHTTP2ToABrokeredNameIsTheRealHosts`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/brokered_test.go#L231)
[`TestEachStreamOfAnHTTP2ConnectionToABrokeredNameCarriesTheRulesHeader`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/brokered_test.go#L251) |
-| Watch where a workspace connects, into its logs | [`spin workspace watch`](/reference/cli/workspace/) | [`TestE2E_AWatchedWorkspacesConnectionsAreInItsLogs`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/seal_test.go#L21), a test of `internal/e2e` | [`TestAnAgentReachesOnlyBrokeredNames`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/brokered_test.go#L138)
[`TestARealWorkspaceMarksTheAgentItsSupervisorStarts`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/cmd/proxy/lane_test.go#L144)
[`workspace-sign-in.spec.ts`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/dashboard/e2e/workspace-sign-in.spec.ts#L31): a visitor signed in to the dashboard reaches their private port |
+| Egress is closed by default; policies, by tag, name what a workspace may reach | [`TestAnOwnerMayOnlyChooseAPolicyTheInstallationDeclares`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/retag_test.go#L163), a test of `internal/e2e` | [`TestAWorkspaceNamedNoPolicyReachesNothing`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/retag_test.go#L71)
[`TestChangingAWorkspacesPoliciesReachesTheHostThatRunsIt`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/retag_test.go#L24) |
+| A policy changed reaches the host that runs the workspace | [`TestChangingAWorkspacesPoliciesReachesTheHostThatRunsIt`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/retag_test.go#L24), a test of `internal/e2e` | [`TestAnEditedPolicyChangesWhatARunningGuestReaches`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/retag_test.go#L100)
[`TestChangingAWorkspacesPoliciesReachesTheHostThatRunsIt`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/retag_test.go#L24) |
+| Brokered names: the host's proxy stands in and adds what the workspace never holds - a team secret, a forge token, its identity, a cloud role
*The team secret's value is read at the origin; the forge token, identity and cloud role injections have no test against the stack.* | [`spin team secret set`](/reference/cli/team/) | [`TestAPersonsRuleAndAnAgentsOnOneNameEachArriveWithTheirOwnInjection`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/brokered_test.go#L100) |
+| A workspace trusts the egress root only by its owner's word | [`TestAGuestTrustsTheEgressRootOnlyByItsOwnersWord`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/egress_root_test.go#L20), a test of `internal/e2e` | [`TestAGuestTrustsTheEgressRootOnlyByItsOwnersWord`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/cmd/cli/e2e_test.go#L792) |
+| 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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/brokered_test.go#L28), a test of `internal/e2e` | [`TestABrokeredRequestIsSeenAsTheProxyReadIt`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/egress_process_test.go#L21), a test of `internal/e2e` | [`TestTheEgressProxyIsAProcessOfItsOwnThatTheRunnerStartsAgain`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/brokered_test.go#L72), a test of `internal/e2e` | [`TestAPersonsRuleAndAnAgentsOnOneNameEachArriveWithTheirOwnInjection`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/brokered_test.go#L100)
[`TestABrokeredNameForTheAgentIsTheAgentsAlone`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/brokered_test.go#L168), a test of `internal/e2e` | [`TestAWebSocketToABrokeredNameCarriesTheGuestsBytesAndRefusesAPathOutOfScope`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/brokered_test.go#L196)
[`TestAWebSocketToABrokeredNameIsCarriedAfterItsHandshake`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/brokered_test.go#L168) |
+| HTTP/2 to a brokered name, the proxy's ALPN the real host's: a rule's headers set stream by stream, gRPC's trailers both ways
*gRPC's trailers are egressproxy's h2 test against an origin of its own; the lane has no gRPC origin to reach.* | [`TestHTTP2ToABrokeredNameIsTheRealHosts`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/brokered_test.go#L231), a test of `internal/e2e` | [`TestHTTP2ToABrokeredNameIsTheRealHosts`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/brokered_test.go#L231)
[`TestEachStreamOfAnHTTP2ConnectionToABrokeredNameCarriesTheRulesHeader`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/brokered_test.go#L251) |
+| Watch where a workspace connects, into its logs | [`spin workspace watch`](/reference/cli/workspace/) | [`TestE2E_AWatchedWorkspacesConnectionsAreInItsLogs`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/seal_test.go#L21), a test of `internal/e2e` | [`TestAnAgentReachesOnlyBrokeredNames`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/brokered_test.go#L138)
[`TestARealWorkspaceMarksTheAgentItsSupervisorStarts`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/cmd/proxy/lane_test.go#L144)
[`workspace-sign-in.spec.ts`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/55e6962b058f3d27f94255704b1ab96250a32de2/cmd/cli/e2e_test.go#L1195)
[`auth.spec.ts`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/cmd/cli/e2e_test.go#L1150) |
-| SSH keys, and plain ssh to spin.<workspace> | [`spin ssh-config`](/reference/cli/ssh-config/) | [`TestE2E_SSHConfigCarriesSSHToAWorkspace`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/cmd/cli/e2e_test.go#L663) |
-| Who logs in to a workspace is what its owner signed | [`TestOnlyThePeopleTheAccessNamesLogInToAWorkspace`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/login_test.go#L259), a test of `internal/e2e` | [`TestOnlyThePeopleTheAccessNamesLogInToAWorkspace`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/identity_test.go#L60), a test of `internal/e2e` | [`TestAWorkspacesIdentityIsTheHostsSignatureOfWhatItsOwnerSigned`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/identity_test.go#L60) |
-| VS Code over SSH, with the server the installation publishes and nothing downloaded
*The server is Microsoft's, for Remote-SSH; spin code also opens an editor with Open Remote - SSH, which downloads its own. spin code itself is run by its unit tests only: it opens a desktop editor, which no lane has.* | [`TestAVSCodeServerOfAnotherCommitIsHandedToTheRunningMachine`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/vscodehotplug_test.go#L23), a test of `internal/e2e` | [`TestTheCarriedVSCodeServerRunsOfflineAndAnswersOverTheSSHTunnel`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/vscodeserver_test.go#L86)
[`TestAVSCodeServerOfAnotherCommitIsHandedToTheRunningMachine`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/cmd/cli/e2e_test.go#L1195)
[`auth.spec.ts`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/cmd/cli/e2e_test.go#L1150) |
+| SSH keys, and plain ssh to spin.<workspace> | [`spin ssh-config`](/reference/cli/ssh-config/) | [`TestE2E_SSHConfigCarriesSSHToAWorkspace`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/cmd/cli/e2e_test.go#L663) |
+| Who logs in to a workspace is what its owner signed | [`TestOnlyThePeopleTheAccessNamesLogInToAWorkspace`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/login_test.go#L259), a test of `internal/e2e` | [`TestOnlyThePeopleTheAccessNamesLogInToAWorkspace`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/identity_test.go#L60), a test of `internal/e2e` | [`TestAWorkspacesIdentityIsTheHostsSignatureOfWhatItsOwnerSigned`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/identity_test.go#L60) |
+| VS Code over SSH, with the server the installation publishes and nothing downloaded
*The server is Microsoft's, for Remote-SSH; spin code also opens an editor with Open Remote - SSH, which downloads its own. spin code itself is run by its unit tests only: it opens a desktop editor, which no lane has.* | [`TestAVSCodeServerOfAnotherCommitIsHandedToTheRunningMachine`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/vscodehotplug_test.go#L23), a test of `internal/e2e` | [`TestTheCarriedVSCodeServerRunsOfflineAndAnswersOverTheSSHTunnel`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/vscodeserver_test.go#L86)
[`TestAVSCodeServerOfAnotherCommitIsHandedToTheRunningMachine`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/) | [`TestTheInstallationFileSeedsAndItsChangesAreAnAdministratorsToDecide`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/config_file_test.go#L92) |
-| Resource presets | [`AdminService/CreateResourcePreset`](/reference/api/adminservice/) | [`admin.spec.ts`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/cmd/cli/e2e_test.go#L606)
[`admin.spec.ts`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/carry_test.go#L21)
[`admin.spec.ts`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/dashboard/e2e/admin.spec.ts#L705): admin runs a job by hand and sees how it ended |
+| Installation settings seeded from a file; a change in the file is a proposal to apply or dismiss | [`AdminService/DecideConfigChange`](/reference/api/adminservice/) | [`TestTheInstallationFileSeedsAndItsChangesAreAnAdministratorsToDecide`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/config_file_test.go#L92) |
+| Resource presets | [`AdminService/CreateResourcePreset`](/reference/api/adminservice/) | [`admin.spec.ts`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/cmd/cli/e2e_test.go#L606)
[`admin.spec.ts`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/carry_test.go#L21)
[`admin.spec.ts`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/rekey_test.go#L24) |
-| Runners: registration tokens, drain, activate, revoke, and a policy per host | [`spin admin runner drain`](/reference/cli/admin/) | [`TestARunnerRegisteredWithATokenTheAPIMadeIsRevokedByTheAdmin`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/runner_token_test.go#L99)
[`TestARegistrationTokenExpiredOrRevokedRegistersNothing`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/runner_token_test.go#L148) |
+| The store: every volume, whose it is, and taking out what nothing needs | [`spin admin storage list`](/reference/cli/admin/) | [`TestAVolumeNothingNeedsIsTakenOutOfTheStore`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/rekey_test.go#L24) |
+| Runners: registration tokens, drain, activate, revoke, and a policy per host | [`spin admin runner drain`](/reference/cli/admin/) | [`TestARunnerRegisteredWithATokenTheAPIMadeIsRevokedByTheAdmin`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/runner_token_test.go#L99)
[`TestARegistrationTokenExpiredOrRevokedRegistersNothing`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/runner_token_test.go#L148) |
| Runners start when a workspace waits for one and stop when nothing runs | [`HostService/GetFleet`](/reference/api/hostservice/) | not yet: an autoscaling group to start and stop: the one group is AWS's, and no lane has an account |
-| A host that reboots brings its workspaces back | [`TestAHostRebootBringsItsWorkspacesBack`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/restart_test.go#L38), a test of `internal/e2e` | [`TestAHostRebootBringsItsWorkspacesBack`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/preemption_test.go#L26), a test of `internal/e2e` | [`TestACloudsReclaimWarningEmptiesTheHostBeforeAnySignal`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/writeback_test.go#L28), a test of `internal/e2e` | [`TestCustomWritebackValuesAreMeasuredOnTheRunner`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/cmd/cli/e2e_test.go#L1052) |
+| A host that reboots brings its workspaces back | [`TestAHostRebootBringsItsWorkspacesBack`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/restart_test.go#L38), a test of `internal/e2e` | [`TestAHostRebootBringsItsWorkspacesBack`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/preemption_test.go#L26), a test of `internal/e2e` | [`TestACloudsReclaimWarningEmptiesTheHostBeforeAnySignal`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/writeback_test.go#L28), a test of `internal/e2e` | [`TestCustomWritebackValuesAreMeasuredOnTheRunner`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/cmd/cli/e2e_test.go#L1052) |
### 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/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/observe_test.go#L22)
[`TestE2E_TheInstallationsLogsAreSearchable`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/cmd/cli/e2e_test.go#L954) |
-| Metrics, with Grafana on the control plane | [`AdminService/GetMonitoring`](/reference/api/adminservice/) | [`admin.spec.ts`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/cmd/cli/e2e_test.go#L975) |
+| Platform logs, workspace logs and traces, searched in the product | [`LogService/SearchPlatformLogs`](/reference/api/logservice/) | [`TestAWorkspacesLinesAndTracesAreFoundBySearchingForIt`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/observe_test.go#L22)
[`TestE2E_TheInstallationsLogsAreSearchable`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/cmd/cli/e2e_test.go#L954) |
+| Metrics, with Grafana on the control plane | [`AdminService/GetMonitoring`](/reference/api/adminservice/) | [`admin.spec.ts`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/cmd/cli/e2e_test.go#L975) |
### 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/55e6962b058f3d27f94255704b1ab96250a32de2/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/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/suspend_test.go#L126), a test of `internal/e2e` | [`TestAMachineAdoptedWithoutItsReleasesIsSuspendedWithItsDisk`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/internal/e2e/suspend_test.go#L126)
[`TestAVSCodeServerOfAnotherCommitIsHandedToTheRunningMachine`](https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/suspend_test.go#L126), a test of `internal/e2e` | [`TestAMachineAdoptedWithoutItsReleasesIsSuspendedWithItsDisk`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/internal/e2e/suspend_test.go#L126)
[`TestAVSCodeServerOfAnotherCommitIsHandedToTheRunningMachine`](https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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 782df37..65e2a84 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 v20261026.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 v20261026.02, 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 bc7b7bb..c59b8b6 100644
--- a/src/data/figures.json
+++ b/src/data/figures.json
@@ -1,6 +1,6 @@
{
"datapath": {
- "source": "https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/docs/network/datapath",
+ "source": "https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/55e6962b058f3d27f94255704b1ab96250a32de2/docs/network/egress-policy",
+ "source": "https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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/55e6962b058f3d27f94255704b1ab96250a32de2/docs/network/isolation",
+ "source": "https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/docs/network/isolation",
"width": 499,
"words": [
"Same address, different segment",
@@ -204,7 +204,7 @@
]
},
"traffic": {
- "source": "https://github.com/spin-stack/spin/blob/55e6962b058f3d27f94255704b1ab96250a32de2/docs/security/traffic",
+ "source": "https://github.com/spin-stack/spin/blob/c02ffc3acfd56cb242d21547cb177da68a3d4f11/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 b1d966c..0ee7dfa 100644
--- a/src/data/reference.json
+++ b/src/data/reference.json
@@ -1,8 +1,8 @@
{
"spin": {
"installs": "v20261025.01",
- "commit": "55e6962b058f3d27f94255704b1ab96250a32de2",
- "tag": "v20261026.01",
+ "commit": "c02ffc3acfd56cb242d21547cb177da68a3d4f11",
+ "tag": "v20261026.02",
"machine": "v20261014.01"
},
"terraform": {
diff --git a/src/data/shots.json b/src/data/shots.json
index 989e4ee..33e1dfe 100644
--- a/src/data/shots.json
+++ b/src/data/shots.json
@@ -1,6 +1,6 @@
{
- "release": "v20261026.01",
- "commit": "55e6962b058f3d27f94255704b1ab96250a32de2",
+ "release": "v20261026.02",
+ "commit": "c02ffc3acfd56cb242d21547cb177da68a3d4f11",
"shots": [
{
"name": "workspaces",
diff --git a/versions.yaml b/versions.yaml
index 89ca57e..81c0e95 100644
--- a/versions.yaml
+++ b/versions.yaml
@@ -7,8 +7,8 @@
- name: spin
kind: git
source: https://github.com/spin-stack/spin
- version: v20261026.01
- pin: 55e6962b058f3d27f94255704b1ab96250a32de2
+ version: v20261026.02
+ pin: c02ffc3acfd56cb242d21547cb177da68a3d4f11
track: github-release
note: >-
The release the site documents (D2: the newest, exactly). The daily sync moves it to the next