fix(k8s): share one pod across task sessions (#3865)
This commit is contained in:
@@ -4,6 +4,11 @@
|
||||
**Date:** 2026-08-24
|
||||
**Area:** backend, frontend, infra, security
|
||||
|
||||
The session-scoped ownership choice is superseded for shared task pods
|
||||
by [task-owned compute](2026-09-21-kubernetes-task-pod-ownership.md).
|
||||
Its exact-resource safety invariants remain in force; existing legacy resources
|
||||
retain their recorded identity until safely adopted.
|
||||
|
||||
## Context
|
||||
|
||||
The Kubernetes executor must combine an administrator-authored Pod template
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
# ADR-2026-09-21-kubernetes-task-pod-ownership: Task-owned Kubernetes compute
|
||||
|
||||
**Status:** accepted
|
||||
**Date:** 2026-09-21
|
||||
**Area:** backend, infra
|
||||
|
||||
## Context
|
||||
|
||||
The user requires one Kubernetes pod per task with multiple agent sessions.
|
||||
The foundation intentionally allocated one pod per lifecycle/session instance.
|
||||
Simply changing resource names would leave session cleanup and authentication
|
||||
owning shared resources, and would race concurrent creation and recovery.
|
||||
|
||||
## Decision
|
||||
|
||||
Make the canonical task environment the durable owner of Kubernetes compute.
|
||||
Sessions own independent agentctl instances inside that pod. Persist physical
|
||||
resource inventory and encrypted control credentials independently of session
|
||||
execution rows; task cleanup owns physical deletion.
|
||||
|
||||
This decision supersedes only the session-scoped ownership choice in
|
||||
[the original ownership ADR](2026-08-24-kubernetes-executor-resource-ownership.md)
|
||||
for newly shared task resources. Exact UID, full ownership validation, admission,
|
||||
create-nonce continuity, launch snapshots, and external-PVC protection remain.
|
||||
Legacy ambiguous multi-pod tasks are never automatically consolidated.
|
||||
Implementation follows the [design](../specs/executors/system-design/kubernetes-task-pod.md); validation evidence is recorded in the [plan](../plans/kubernetes-task-pod/plan.md).
|
||||
|
||||
## Consequences
|
||||
|
||||
Additional sessions share workspace data and compute without duplicate pods.
|
||||
Pod failure affects all attached sessions. Durable environment inventory and
|
||||
creation/deletion exclusion are required even when no sessions remain.
|
||||
Compatibility must preserve legacy independent workspaces and recorded identities.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
- Keep per-session pods: violates the requested compute and workspace contract.
|
||||
- Change names to task IDs only: leaves races, per-session cleanup, and control
|
||||
authentication unresolved.
|
||||
- Reuse an arbitrary sibling execution: loses ownership when that session is
|
||||
deleted and cannot safely choose among legacy independent workspaces.
|
||||
@@ -0,0 +1,41 @@
|
||||
# ADR-2026-09-23-kubernetes-task-trust-boundary: Shared task credential trust
|
||||
|
||||
**Status:** accepted
|
||||
**Date:** 2026-09-23
|
||||
**Area:** backend, infra
|
||||
|
||||
## Context
|
||||
|
||||
[Task-owned Kubernetes compute](2026-09-21-kubernetes-task-pod-ownership.md)
|
||||
places independent agent sessions in one container under one OS user. Separate
|
||||
HOME paths and private file permissions prevent accidental configuration mixing,
|
||||
but sibling processes can read each other's credentials. A security review
|
||||
required an explicit boundary before supporting different credential bindings.
|
||||
The user selected shared task trust on 2026-09-23.
|
||||
|
||||
## Decision
|
||||
|
||||
Treat every session in a task as mutually trusted. Allow different agent profiles
|
||||
and credentials in the shared pod. Per-session environment and auth preparation
|
||||
must preserve each session's launch settings, without claiming security isolation
|
||||
from other sessions. Operators own agent trust and provider-side credential
|
||||
revocation. Document this boundary in the public Kubernetes executor guide.
|
||||
|
||||
## Consequences
|
||||
|
||||
A compromised agent can expose sibling credentials. Operators must stop the task's
|
||||
agents and revoke or rotate exposed credentials with their providers. Stopping or
|
||||
deleting one session cannot undo exposure. Agents requiring separate trust must
|
||||
use separate tasks with appropriate executor isolation policies.
|
||||
|
||||
Regression tests verify that different profiles and credentials share one pod
|
||||
while retaining distinct launch configuration. They do not claim same-UID access
|
||||
is prevented. The [requirements](../specs/executors/requirements/kubernetes-task-pod.md)
|
||||
and [design](../specs/executors/system-design/kubernetes-task-pod.md) define this contract.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
- Reject differing credential bindings: limits multi-profile tasks and does not
|
||||
isolate other same-UID secrets. The user chose to permit differing bindings.
|
||||
- Separate OS identities or a credential broker: changes the executor security
|
||||
architecture and operational contract; not selected for shared task trust.
|
||||
@@ -0,0 +1,152 @@
|
||||
---
|
||||
created: 2026-09-21
|
||||
status: done
|
||||
requirements:
|
||||
- REQ-EXECUTORS-KUBERNETES-TASK-POD-001
|
||||
system_design:
|
||||
- ../../specs/executors/system-design/kubernetes-task-pod.md
|
||||
legacy_specs:
|
||||
- ../../specs/kubernetes-executor/spec.md
|
||||
---
|
||||
|
||||
# Implementation Plan: Kubernetes task pod
|
||||
|
||||
## Overview
|
||||
|
||||
Replace per-session pod allocation with one task-owned pod containing independent
|
||||
agentctl instances. Deliver additive durable inventory first, integrate lifecycle
|
||||
ownership second, and prove the full flow with Kind plus operator documentation.
|
||||
All three work orders are complete.
|
||||
|
||||
## Scope
|
||||
|
||||
### In scope
|
||||
|
||||
Task-owned Pod/PVC inventory and control credentials, safe session attachment,
|
||||
concurrent creation/recovery, session-only termination, task-owned cleanup,
|
||||
status projection, and non-destructive legacy compatibility.
|
||||
|
||||
### Out of scope
|
||||
|
||||
Cross-task pod pooling, automatic merging of existing pods/workspaces, new UI
|
||||
controls, and changing workspace inheritance or executor-transition semantics.
|
||||
|
||||
## Confirmed evidence
|
||||
|
||||
Source trace, not a reproduction on the user's cluster:
|
||||
`KubernetesExecutor.CreateInstance` locks by execution ID and chooses
|
||||
`createFresh` without recorded pod metadata. `newKubernetesFreshLaunch` calls
|
||||
`kubernetesResourceNames(req.InstanceID)`, so different sessions create different
|
||||
pods. The foundation explicitly requires one pod per session and excludes
|
||||
concurrent sharing. `StopInstance` also owns terminal pod deletion. The requested
|
||||
behavior therefore changes physical ownership, not just a reuse lookup.
|
||||
|
||||
Smallest reproduction: create session A and then session B in the same ready
|
||||
Kubernetes task environment with distinct execution IDs; compare Pod UIDs and
|
||||
managed PVCs. The regression must assert one pod, one claim, two agentctl
|
||||
instances, and unchanged workspace content.
|
||||
|
||||
## Technical approach
|
||||
|
||||
Follow the [design](../../specs/executors/system-design/kubernetes-task-pod.md)
|
||||
and [requirements](../../specs/executors/requirements/kubernetes-task-pod.md).
|
||||
Add `task_environment_kubernetes` with durable operation/generation exclusion and
|
||||
secret references through the existing task repository and lifecycle adapters.
|
||||
Keep `executors_running` per-session. Integrate create, attach, reconnect,
|
||||
checkpoint, refresh, stop, cleanup, and session-status resolution together so no
|
||||
intermediate shared-resource path retains destructive session cleanup.
|
||||
|
||||
## Tests
|
||||
|
||||
Proposed regression files/methods (names are implementation targets):
|
||||
|
||||
| Criteria | Evidence |
|
||||
| --- | --- |
|
||||
| AC-EXECUTORS-KUBERNETES-TASK-POD-001.1, .2 | `executor_kubernetes_task_pod_test.go`: `TestKubernetesTaskPodAdditionalSession`, `TestKubernetesTaskPodConcurrentAttach`; independent env/auth and unchanged files |
|
||||
| AC-EXECUTORS-KUBERNETES-TASK-POD-001.2, .4, .5 | `environment_kubernetes_test.go`: `TestKubernetesEnvironmentClaimExclusion`, `TestKubernetesEnvironmentRestartReplay`; PostgreSQL multi-connection counterparts |
|
||||
| AC-EXECUTORS-KUBERNETES-TASK-POD-001.3, .5 | `executor_kubernetes_task_pod_test.go`: `TestKubernetesTaskPodStopPreservesSibling`, `TestKubernetesTaskPodTerminalCleanup`; live + failed mixed rows |
|
||||
| AC-EXECUTORS-KUBERNETES-TASK-POD-001.4, .6 | `executor_kubernetes_task_pod_test.go`: `TestKubernetesTaskPodConcurrentRecovery`, `TestKubernetesTaskPodLegacyAmbiguity`; foreign UID, partial failure, retained zero-session inventory |
|
||||
| AC-EXECUTORS-KUBERNETES-TASK-POD-001.7 | `sessions_task_pod_test.go`: `TestSessionsSharedTaskPod`; lifecycle profile pinning and instance environment tests |
|
||||
|
||||
## E2E tests
|
||||
|
||||
Add `apps/web/e2e/tests/kubernetes/kubernetes-task-pod.spec.ts` in the
|
||||
`containers` project using the existing disposable Kind fixture. Cover criteria
|
||||
.1 through .5 and .7 with sequential and concurrent second-session creation,
|
||||
shared files, stop-one, backend restart/resume, and final archive cleanup.
|
||||
Criterion .6 uses exact fake-client/repository tests, with a Kind ownership
|
||||
mismatch scenario if the existing fixture can inject it safely.
|
||||
No rendering change is planned; desktop/mobile consume the same status contract.
|
||||
|
||||
## Work orders
|
||||
|
||||
- [x] [Task 01: Durable environment inventory](task-01-durable-inventory.md)
|
||||
- [x] [Task 02: Shared pod lifecycle](task-02-shared-lifecycle.md)
|
||||
- [x] [Task 03: Kind evidence and operator docs](task-03-kind-docs.md)
|
||||
|
||||
## Verification results
|
||||
|
||||
SQLite and PostgreSQL inventory regressions pass with race detection. The targeted
|
||||
Kubernetes lifecycle, task service, status, orchestrator executor, and backend
|
||||
wiring packages pass with race detection. Eleven desktop/mobile component tests
|
||||
pass. Public-doc validators, spec catalog/linter, and SQL guard pass.
|
||||
|
||||
The Kind regression passed (1 test, 6.9 minutes), proving three concurrent/shared
|
||||
sessions in one Pod UID and one managed PVC, distinct per-session auth files,
|
||||
shared untracked data, force-stop isolation, a real response after backend
|
||||
restart, healthy status rows, and final archive deletion of the Pod/PVC.
|
||||
|
||||
Live runs exposed and fixed task-delete inventory retention, private HOME creation,
|
||||
and missing persistent ownership markers. The passing run also exposed a cleanup
|
||||
retry after local execution identity changed. A follow-up failing-then-passing
|
||||
regression verifies exact remote-session connection cleanup after that rebind;
|
||||
the final lifecycle race suite and lint pass. Kind was not repeated after this
|
||||
narrow connection-cleanup fix.
|
||||
|
||||
Cold-host setup required temporary image-load/fixture deadlines. Those edits were
|
||||
restored; the test itself uses a supported 120-second executor request timeout for
|
||||
cold PVC provisioning. All disposable Kind clusters were removed by teardown.
|
||||
|
||||
Mobile state-only change: use a task/session composite row identity so multiple
|
||||
retained task Pods without sessions stay distinct. Existing desktop table and
|
||||
mobile linked cards keep their composition and touch behavior. Targeted component
|
||||
coverage exercises both layouts; no new viewport interaction is introduced.
|
||||
|
||||
## PR remediation
|
||||
|
||||
Review fixes add typed agentctl not-found errors, request-scoped canonical
|
||||
inventory/Pod caching, required-table upgrade probes, and concurrent stop/attach
|
||||
coverage. Credential persistence recovery retains the issued token until its
|
||||
canonical encrypted record is saved, using an encrypted recovery secret across
|
||||
backend restart. Cleanup detaches cancellation with a one-minute budget. Updated backend guidance distinguishes
|
||||
physical environment ownership from per-session inventory.
|
||||
|
||||
CI remediation also incorporates the current base and fills 32 missing Japanese
|
||||
SSH strings. The base's preview-feedback subscription requires an updated exact
|
||||
subscription count; no WebSocket production behavior changes for that fix.
|
||||
Post-fix verification: targeted lifecycle/status race regressions, the full
|
||||
agentctl race suite, SQLite store conformance and previous-stable upgrades pass.
|
||||
The WebSocket subscription regression passes 20 race-enabled runs. Full i18n
|
||||
checks and three current component tests pass; harness/spec checks pass.
|
||||
Remote CI/review completion remains pending. The user selected shared task trust on 2026-09-23: differing profiles and credentials
|
||||
are allowed, and same-UID sibling credential access is accepted. The trust ADR,
|
||||
requirements, design and public guide record operator trust and revocation duties.
|
||||
|
||||
## Risks
|
||||
|
||||
Control authentication and bootstrap files currently assume one session; sharing
|
||||
must not replace sibling credentials. Legacy tasks can contain genuinely different
|
||||
workspaces. Durable claims must recover after crashes without duplicate API creates.
|
||||
Public docs reflect the implemented and verified behavior. Persistence coverage requires a disposable
|
||||
PostgreSQL database; Kind coverage requires Docker and the pinned worker image.
|
||||
|
||||
## 2026-09-23 fixup validation
|
||||
|
||||
Merged main and resolved Japanese catalog conflicts while preserving all keys and
|
||||
removing duplicate keys. Both CI assertion failures reproduced locally: ownership
|
||||
coverage expected obsolete error text, and resume observations were asynchronous.
|
||||
Typed error assertions and synchronized resume coverage now pass 20 race-enabled
|
||||
runs, as does the shared-pod suite with differing agent profiles and credentials.
|
||||
Full orchestrator executor and agentctl API race suites pass. Translation checks,
|
||||
specification validation and all 199 harness files pass. Postgres CI failed while
|
||||
downloading protobuf from the Go proxy; the next head will rerun that job.
|
||||
@@ -0,0 +1,106 @@
|
||||
---
|
||||
id: "01-durable-inventory"
|
||||
title: "Durable environment inventory"
|
||||
status: done
|
||||
wave: 1
|
||||
depends_on: []
|
||||
plan: "plan.md"
|
||||
requirements:
|
||||
- REQ-EXECUTORS-KUBERNETES-TASK-POD-001
|
||||
acceptance_criteria:
|
||||
- AC-EXECUTORS-KUBERNETES-TASK-POD-001.2
|
||||
- AC-EXECUTORS-KUBERNETES-TASK-POD-001.4
|
||||
- AC-EXECUTORS-KUBERNETES-TASK-POD-001.5
|
||||
- AC-EXECUTORS-KUBERNETES-TASK-POD-001.6
|
||||
system_design:
|
||||
- ../../specs/executors/system-design/kubernetes-task-pod.md
|
||||
---
|
||||
|
||||
# Task 01: Durable environment inventory
|
||||
|
||||
## Summary
|
||||
|
||||
Add the durable environment-level Kubernetes inventory and conditional operation
|
||||
claims as a compatible expansion. Existing lifecycle behavior remains unchanged
|
||||
until Task 02 wires the new record into allocation and cleanup.
|
||||
|
||||
## In scope
|
||||
|
||||
- Typed runtime record, secret references, schema initialization and replayable migration.
|
||||
- Transactional create/recover/delete claims and generation checks on both dialects.
|
||||
- Legacy inventory classification is integrated and tested in Task 02 at the lifecycle consumer.
|
||||
|
||||
## Out of scope
|
||||
|
||||
Cross-task pooling, automated legacy consolidation, and UI redesign.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- Concurrent claims elect one owner and cannot overlap deletion with attachment.
|
||||
- Restart replay preserves exact inventory and secret references; migration deletes no remote resources or legacy rows.
|
||||
- Changed ownership generations and stale cleanup operations cannot overwrite or release inventory.
|
||||
|
||||
## Verification
|
||||
|
||||
Use TDD for changed logic: run the named regression before and after implementation.
|
||||
Commands run from repository root. Read scoped guidance and applicable TDD/E2E
|
||||
skills before implementation.
|
||||
|
||||
```bash
|
||||
(cd apps/backend && go test -tags fts5 ./internal/task/repository/sqlite -run 'KubernetesEnvironment' -count=1)
|
||||
(cd apps/backend && go test -race -tags fts5 ./internal/task/repository/sqlite -run 'KubernetesEnvironment' -count=1)
|
||||
(cd apps/backend && go run ./cmd/sqlguard ./internal)
|
||||
(cd apps/backend && go test -race ./internal/persistence/storeconformance -count=1)
|
||||
```
|
||||
|
||||
## Files likely touched
|
||||
|
||||
- `apps/backend/internal/task/models/models.go`
|
||||
- `apps/backend/internal/task/repository/sqlite/environment.go`
|
||||
- New `apps/backend/internal/task/repository/sqlite/environment_kubernetes.go` and `_test.go`
|
||||
- `apps/backend/internal/task/repository/sqlite/base_migrations.go` and schema/replay fixtures
|
||||
- Task repository interface and lifecycle/backendapp adapters needed by the typed record
|
||||
|
||||
## Dependencies
|
||||
|
||||
None.
|
||||
|
||||
## Risks
|
||||
|
||||
Claims require real PostgreSQL multi-connection evidence using `KANDEV_TEST_POSTGRES_DSN`; an unset variable is skipped coverage, not a pass.
|
||||
|
||||
## Parallelism
|
||||
|
||||
`sequential`
|
||||
|
||||
## Inputs
|
||||
|
||||
- [Requirements](../../specs/executors/requirements/kubernetes-task-pod.md).
|
||||
- [System design](../../specs/executors/system-design/kubernetes-task-pod.md).
|
||||
- [Plan](plan.md) regression matrix.
|
||||
- Existing `executor_kubernetes_fakes_test.go`, checkpoint/restart tests, and
|
||||
task environment repository tests as patterns.
|
||||
|
||||
## Results
|
||||
|
||||
Passed targeted KubernetesEnvironment tests with SQLite and disposable PostgreSQL,
|
||||
including the race detector. Passed `go run ./cmd/sqlguard ./internal` and
|
||||
`go test -race ./internal/persistence/storeconformance -count=1`.
|
||||
|
||||
Initial inventory regression failed with missing table; claim regression failed
|
||||
with missing repository capability; stale-generation checkpoint failed because
|
||||
it accepted an outdated owner. Each passed after its implementation.
|
||||
Checks used `GOCACHE=/tmp/kandev-kube-pod-gocache-87d89c84` because unrelated
|
||||
shared-cache removal interrupted the first broad compiler runs.
|
||||
PostgreSQL used an isolated Docker container on loopback port 36019.
|
||||
|
||||
|
||||
Live validation exposed the task-delete cascade preceding asynchronous cleanup.
|
||||
The regression failed with a foreign-key error and now passes on SQLite and
|
||||
PostgreSQL: physical inventory survives task deletion, normal launch claims
|
||||
reject deleted owners, and cleanup claims retain exact generation/revision
|
||||
fencing. Direct environment deletion remains guarded until remote cleanup.
|
||||
|
||||
## PR remediation
|
||||
|
||||
PR remediation adds task_environment_kubernetes to the required-table probe; SQLite conformance and previous-stable upgrade tests pass with race detection.
|
||||
@@ -0,0 +1,116 @@
|
||||
---
|
||||
id: "02-shared-lifecycle"
|
||||
title: "Shared pod lifecycle"
|
||||
status: done
|
||||
wave: 2
|
||||
depends_on:
|
||||
- "01-durable-inventory"
|
||||
plan: "plan.md"
|
||||
requirements:
|
||||
- REQ-EXECUTORS-KUBERNETES-TASK-POD-001
|
||||
acceptance_criteria:
|
||||
- AC-EXECUTORS-KUBERNETES-TASK-POD-001.1
|
||||
- AC-EXECUTORS-KUBERNETES-TASK-POD-001.2
|
||||
- AC-EXECUTORS-KUBERNETES-TASK-POD-001.3
|
||||
- AC-EXECUTORS-KUBERNETES-TASK-POD-001.4
|
||||
- AC-EXECUTORS-KUBERNETES-TASK-POD-001.5
|
||||
- AC-EXECUTORS-KUBERNETES-TASK-POD-001.6
|
||||
- AC-EXECUTORS-KUBERNETES-TASK-POD-001.7
|
||||
system_design:
|
||||
- ../../specs/executors/system-design/kubernetes-task-pod.md
|
||||
---
|
||||
|
||||
# Task 02: Shared pod lifecycle
|
||||
|
||||
## Summary
|
||||
|
||||
Wire task-owned inventory into the complete Kubernetes lifecycle. Start additional
|
||||
sessions as independent agentctl instances in the canonical pod and remove all
|
||||
session-level authority to destroy shared compute.
|
||||
|
||||
## In scope
|
||||
|
||||
- Fresh create, attach-only admission, per-instance configuration, secret resolution, and pinned workload snapshot.
|
||||
- Generation-guarded reconnect/replacement, checkpoints, partial-failure rollback, and restart refresh.
|
||||
- Session-only termination, final task cleanup, zero-session retention, legacy compatibility, and authorized status projection.
|
||||
|
||||
## Out of scope
|
||||
|
||||
Cross-task pooling, automated legacy consolidation, and UI redesign.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- The two-session regression fails before the change and passes with one Pod/PVC and distinct agentctl instances; concurrent attach never creates another pod.
|
||||
- Stop/delete/force/failure of one session leaves a live sibling usable; task cleanup excludes new attachment and deletes only exact owned resources.
|
||||
- Restart, legacy ambiguity, foreign identity, profile edits, independent runtime env, and status projection pass targeted regressions.
|
||||
|
||||
## Verification
|
||||
|
||||
Use TDD for changed logic: run the named regression before and after implementation.
|
||||
Commands run from repository root. Read scoped guidance and applicable TDD/E2E
|
||||
skills before implementation.
|
||||
|
||||
```bash
|
||||
(cd apps/backend && go test -race -tags fts5 ./internal/agent/kubernetes ./internal/agent/runtime/lifecycle ./internal/task/service ./internal/kubernetes ./internal/orchestrator/executor ./internal/backendapp -run 'Kubernetes|SharedTaskPod' -count=1)
|
||||
```
|
||||
|
||||
## Files likely touched
|
||||
|
||||
- `apps/backend/internal/agent/runtime/lifecycle/executor_kubernetes.go`
|
||||
- Kubernetes lifecycle bootstrap, identity, reconnect, cleanup, refresh, and checkpoint files
|
||||
- New `apps/backend/internal/agent/runtime/lifecycle/executor_kubernetes_task_pod_test.go`
|
||||
- `apps/backend/internal/agent/kubernetes/compose.go` and ownership/admission tests
|
||||
- `apps/backend/internal/task/service/service_resources.go` and Kubernetes resource cleanup tests
|
||||
- `apps/backend/internal/kubernetes/sessions.go`, `sessions_retention.go`, and new `sessions_task_pod_test.go`
|
||||
- `apps/backend/internal/orchestrator/executor/` and `apps/backend/internal/backendapp/` launch/cleanup adapters
|
||||
|
||||
## Dependencies
|
||||
|
||||
01-durable-inventory.
|
||||
|
||||
## Risks
|
||||
|
||||
Do not copy sibling execution metadata wholesale, rerun pod-wide bootstrap on attach, or treat force-stop as task deletion authority.
|
||||
|
||||
## Parallelism
|
||||
|
||||
`sequential`
|
||||
|
||||
## Inputs
|
||||
|
||||
- [Requirements](../../specs/executors/requirements/kubernetes-task-pod.md).
|
||||
- [System design](../../specs/executors/system-design/kubernetes-task-pod.md).
|
||||
- [Plan](plan.md) regression matrix.
|
||||
- Existing `executor_kubernetes_fakes_test.go`, checkpoint/restart tests, and
|
||||
task environment repository tests as patterns.
|
||||
|
||||
## Results
|
||||
|
||||
Targeted Kubernetes package tests passed with `-race -tags fts5`. Added regressions
|
||||
cover independent agent environments, concurrent attachment, session-only stop,
|
||||
exact task cleanup, backend/container/Pod recovery, stale-token protection,
|
||||
secret/inventory/connection failure rollback, legacy conflicts and adopted-resource
|
||||
protection, retained zero-session status, and executor deletion guards.
|
||||
|
||||
Startup fences interrupted claims under the existing exclusive runtime-state lock.
|
||||
Incomplete bootstrap inventory remains available for exact cleanup and blocks
|
||||
unsafe attachment. Desktop and mobile retained-row component tests passed.
|
||||
|
||||
Kind validation additionally exposed two integration gaps that unit fixtures did
|
||||
not cover: creating private HOME before credential-less session preparation, and
|
||||
preserving shared ownership/version markers through execution metadata filtering.
|
||||
Both have failing-before/passing-after regressions. The final targeted lifecycle,
|
||||
orchestrator executor, and status packages pass with race detection; scoped
|
||||
lifecycle lint reports zero issues. The live test proves three sessions in one
|
||||
Pod UID and a sibling continuing after force-stopping the creator; restart and
|
||||
final cleanup subsequently passed in work order 03.
|
||||
|
||||
The passing Kind run exposed a transient cleanup retry after execution identity
|
||||
rebinding. The final regression reproduces stopping the same remote session with
|
||||
a new local execution ID and verifies immediate task cleanup. Exact task/session/
|
||||
environment/remote-instance matching closes its original local connection while
|
||||
leaving siblings intact. Final lifecycle race tests pass (8.512s); lint is clean.
|
||||
|
||||
## PR remediation
|
||||
|
||||
PR remediation adds typed not-found errors, encrypted credential recovery across backend restart, concurrent stop/attach coverage, and bounded cancellation-detached cleanup. Targeted race coverage passes; the user accepted shared task credential trust on 2026-09-23. Different profiles and credentials remain supported; the trust ADR and public guide describe sibling access and operator revocation responsibilities.
|
||||
@@ -0,0 +1,112 @@
|
||||
---
|
||||
id: "03-kind-docs"
|
||||
title: "Kind evidence and operator docs"
|
||||
status: done
|
||||
wave: 3
|
||||
depends_on:
|
||||
- "02-shared-lifecycle"
|
||||
plan: "plan.md"
|
||||
requirements:
|
||||
- REQ-EXECUTORS-KUBERNETES-TASK-POD-001
|
||||
acceptance_criteria:
|
||||
- AC-EXECUTORS-KUBERNETES-TASK-POD-001.1
|
||||
- AC-EXECUTORS-KUBERNETES-TASK-POD-001.2
|
||||
- AC-EXECUTORS-KUBERNETES-TASK-POD-001.3
|
||||
- AC-EXECUTORS-KUBERNETES-TASK-POD-001.4
|
||||
- AC-EXECUTORS-KUBERNETES-TASK-POD-001.5
|
||||
- AC-EXECUTORS-KUBERNETES-TASK-POD-001.6
|
||||
- AC-EXECUTORS-KUBERNETES-TASK-POD-001.7
|
||||
system_design:
|
||||
- ../../specs/executors/system-design/kubernetes-task-pod.md
|
||||
---
|
||||
|
||||
# Task 03: Kind evidence and operator docs
|
||||
|
||||
## Summary
|
||||
|
||||
Prove the user-visible second-session flow on disposable Kind and update the
|
||||
operator lifecycle documentation after the implementation is verified.
|
||||
|
||||
## In scope
|
||||
|
||||
- Two sessions, one exact pod and managed PVC, shared untracked file, and distinct agent instances.
|
||||
- Stop-one/sibling-live, backend restart/resume, concurrent second launch, and final archive cleanup.
|
||||
- Foundation/ADR compatibility notes, public Kubernetes guide, backend engineering ownership guidance, and implementation result/status updates.
|
||||
|
||||
## Out of scope
|
||||
|
||||
Cross-task pooling, automated legacy consolidation, and UI redesign.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- Kind evidence proves the shared lifecycle and unchanged workspace without operating on the user's cluster.
|
||||
- Public docs explain task-owned resources, independent sessions, and the non-destructive legacy limitation.
|
||||
- Each earlier work order records actual command results and the design matches the implemented boundaries.
|
||||
|
||||
## Verification
|
||||
|
||||
Use TDD for changed logic: run the named regression before and after implementation.
|
||||
Commands run from repository root. Read scoped guidance and applicable TDD/E2E
|
||||
skills before implementation.
|
||||
|
||||
```bash
|
||||
(cd apps && pnpm install --frozen-lockfile)
|
||||
(cd apps/web && KANDEV_E2E_CONTAINERS=1 pnpm e2e:run --host --project containers tests/kubernetes/kubernetes-task-pod.spec.ts)
|
||||
node --test scripts/validate-public-docs.test.mjs
|
||||
node scripts/validate-public-docs.mjs
|
||||
python3 scripts/list-docs.py validate
|
||||
python3 scripts/lint-spec-files.py --all
|
||||
git diff --check
|
||||
```
|
||||
|
||||
## Files likely touched
|
||||
|
||||
- New `apps/web/e2e/tests/kubernetes/kubernetes-task-pod.spec.ts`
|
||||
- `apps/web/e2e/fixtures/kubernetes-test-base.ts` only if a bounded fixture extension is needed
|
||||
- `docs/public/k8s.md` (reference/how-to lifecycle wording) and `docs/k8s.md` if duplicated
|
||||
- `docs/specs/kubernetes-executor/spec.md`
|
||||
- `docs/specs/executors/README.md` and the task-pod requirement/design pair
|
||||
- `apps/backend/AGENTS.md`
|
||||
- This plan and its three work orders
|
||||
|
||||
## Dependencies
|
||||
|
||||
02-shared-lifecycle.
|
||||
|
||||
## Risks
|
||||
|
||||
Requires Docker/Kind; use existing guarded host-mode runner. Do not claim skipped E2E as verified or publish draft behavior as already available.
|
||||
|
||||
## Parallelism
|
||||
|
||||
`sequential`
|
||||
|
||||
## Inputs
|
||||
|
||||
- [Requirements](../../specs/executors/requirements/kubernetes-task-pod.md).
|
||||
- [System design](../../specs/executors/system-design/kubernetes-task-pod.md).
|
||||
- [Plan](plan.md) regression matrix.
|
||||
- Existing `executor_kubernetes_fakes_test.go`, checkpoint/restart tests, and
|
||||
task environment repository tests as patterns.
|
||||
|
||||
## Results
|
||||
|
||||
Passed the disposable Kind scenario: 1 test in 6.9 minutes. Three sessions shared
|
||||
one Pod UID and managed PVC; independent auth files and shared untracked data were
|
||||
verified. Force-stopping the creator preserved a sibling, a new response arrived
|
||||
after backend restart, status rows were healthy, and archive removed Pod/PVC.
|
||||
|
||||
The passing run exposed a transient cleanup retry when a resumed execution used a
|
||||
new local ID. A follow-up lifecycle regression reproduced the stale connection,
|
||||
and the exact-session cleanup fix passes the final Kubernetes race suite and
|
||||
lint. The Kind scenario was not repeated after this narrow fix.
|
||||
|
||||
Eleven desktop/mobile component tests, frontend lint, 62 public-doc validator
|
||||
tests, public-doc validation (47 pages), specification catalog/linter, and
|
||||
`git diff --check` passed. Temporary Kind setup timeout edits were restored.
|
||||
Operator docs, foundation compatibility notes, ADR, backend guidance, requirements,
|
||||
and design now describe the implemented task-owned lifecycle.
|
||||
|
||||
## PR remediation
|
||||
|
||||
PR remediation caches canonical inventory and Pod probes per status request and corrects ownership guidance. Targeted status race coverage and three current frontend component tests pass. Kind evidence above remains historical; this remediation did not repeat Kind.
|
||||
@@ -21,7 +21,7 @@ An executor determines where Kandev creates a task environment and runs `agentct
|
||||
| Worktree | Supported; normal default | Dedicated Git worktree on the Kandev host | Parallel coding on a trusted machine |
|
||||
| Local | Supported | The selected checkout, or an explicit folder for a repository-free task | One controlled task must work in that exact folder |
|
||||
| Local Docker | Supported when the global Docker runtime is enabled and its daemon is reachable | `/workspace` in a new Docker container | You need a repeatable container boundary |
|
||||
| Kubernetes | Dependency-bound on cluster access, namespaced RBAC, admission, storage, and streaming support | `/workspace` in one Pod per task session | You need sessions scheduled inside an administrator-managed cluster boundary |
|
||||
| Kubernetes | Dependency-bound on cluster access, namespaced RBAC, admission, storage, and streaming support | `/workspace` in one Pod per task | You need sessions scheduled inside an administrator-managed cluster boundary |
|
||||
| Sprites.dev | Supported, provider-dependent | `/workspace` in a provider sandbox | You need remote compute and accept provider lifecycle/billing |
|
||||
| SSH | Supported for repository sources on a trusted host | A task folder on a trusted SSH host | You need a remote host with SSH, SFTP, forwarding, and clone credentials |
|
||||
| Remote Docker | **Not implemented** | None | Do not select or create this type |
|
||||
@@ -317,7 +317,7 @@ docker ps -a --filter label=kandev.managed=true
|
||||
|
||||
> **Cluster authority:** A Kubernetes profile is an administrator-authored Pod template. It can request powerful workload settings, and every injected task credential is available to the main container. Use admission policy, a dedicated namespace, a narrowly scoped API identity, and a separate workload service account.
|
||||
|
||||
Kubernetes maps one task session to one namespaced Pod and reaches the injected `agentctl` through a process-local `127.0.0.1` port-forward. The backend can authenticate from an absolute kubeconfig path on the Kandev host or from its own in-cluster service account. It never falls back to a local executor when cluster configuration, admission, exec, or port-forward fails.
|
||||
Kubernetes maps one task to one namespaced Pod, with an independent agentctl instance for each session, and reaches the injected `agentctl` through a process-local `127.0.0.1` port-forward. The backend can authenticate from an absolute kubeconfig path on the Kandev host or from its own in-cluster service account. It never falls back to a local executor when cluster configuration, admission, exec, or port-forward fails.
|
||||
|
||||
The current experimental matrix validates API and `agentctl` connectivity on Kubernetes 1.34.8 and 1.36.1 and runs the full lifecycle suite on 1.36.1. Other server versions have not yet been validated.
|
||||
|
||||
@@ -331,7 +331,7 @@ Each executor fixes one namespace and connection configuration. Each profile sup
|
||||
|
||||
| Workspace mode | Persistence and ownership |
|
||||
|---|---|
|
||||
| Managed PVC | Kandev creates one claim for the session, preserves it across ordinary stop, backend restart, and Pod replacement, then deletes it only during terminal or forced cleanup after exact identity checks. |
|
||||
| Managed PVC | Kandev creates one claim for the task, preserves it across ordinary stop, backend restart, and Pod replacement, then deletes it only during task archive/delete cleanup after exact identity checks. |
|
||||
| `emptyDir` | Fast Pod-scoped storage. It survives a main-container restart but is lost with the Pod, so a missing Pod cannot be recovered. No PVC permission is required. |
|
||||
| Existing claim | Kandev verifies and mounts the named claim in the executor namespace. It never creates or deletes that claim. Concurrent-access safety depends on the claim and application. |
|
||||
|
||||
@@ -345,9 +345,9 @@ an immutable registry digest. The current Kind evidence covers Linux `amd64`
|
||||
only. These files are profile inputs, not standalone Pod manifests; Kandev
|
||||
continues to own bootstrap, credentials, runtime mounts, and the workspace.
|
||||
|
||||
Ordinary Stop, agent restart, main-container restart, and backend restart preserve the Pod and workspace. Resume verifies the recorded name, UID, and complete ownership-label identity, creates a new local port-forward, and reconnects. Every managed create also carries a fresh 256-bit request nonce so an ambiguous API response cannot make Kandev adopt or delete a copied-label object. Archive/delete terminal cleanup or an explicit force cleanup deletes only the exact recorded Pod and, for managed storage, the exact Kandev-created PVC. A same-name object with another UID, ownership identity, or create nonce is left untouched and cleanup fails closed.
|
||||
Stop, including force-stop, removes only the selected agentctl instance. Other sessions and the task workspace remain available. Agent, main-container, and backend restarts preserve the Pod and workspace. Resume verifies the recorded name, UID, and complete ownership-label identity, creates a new local port-forward, and reconnects. Every managed create also carries a fresh 256-bit request nonce so an ambiguous API response cannot make Kandev adopt or delete a copied-label object. Task archive/delete cleanup deletes only the exact recorded Pod and, for managed storage, the exact Kandev-created PVC. A same-name object with another UID, ownership identity, or create nonce is left untouched and cleanup fails closed.
|
||||
|
||||
Saved executor connection settings are different from the recorded workload snapshot. Current kubeconfig/in-cluster credentials, context, and timeout are used to reach an existing session; changing them can restore or break reconnect and cleanup. Existing sessions continue to target their recorded namespace even if the saved namespace changes, and the saved namespace affects new sessions only. Current Pod template, image, platform, main container, and storage settings also affect new sessions only. If Kandev must replace a missing Pod, it uses the recorded namespace and workload snapshot rather than the edited profile.
|
||||
Saved executor connection settings are different from the recorded workload snapshot. Current kubeconfig/in-cluster credentials, context, and timeout are used to reach an existing session; changing them can restore or break reconnect and cleanup. Existing sessions continue to target their recorded namespace even if the saved namespace changes, and the saved namespace affects new task Pods only. Current Pod template, image, platform, main container, and storage settings also affect new task Pods only; additional sessions reuse the task's recorded workload. If Kandev must replace a missing Pod, it uses the recorded namespace and workload snapshot rather than the edited profile.
|
||||
|
||||
An executor cannot be deleted or changed into or out of Kubernetes while runtime inventory still references it. Clear the sessions through normal terminal cleanup first; deleting a profile does not mutate or destroy a retained workload.
|
||||
|
||||
@@ -358,7 +358,7 @@ memory values are requests from the verified Pod spec, not actual usage or
|
||||
cost. Stop preserves a resumable Kandev-managed workspace; Archive or Delete
|
||||
can remove it. Kandev does not delete an operator-owned existing claim.
|
||||
|
||||
See [Kubernetes](k8s.md#configure-the-kubernetes-executor) for kubeconfig and in-cluster setup, the opt-in namespaced RBAC manifest, exact ownership labels, diagnostics, template rules, and recovery guidance.
|
||||
All sessions in a task share one credential trust boundary. Same-UID agents can read sibling credentials even when their profiles differ. Operators must trust every attached agent and revoke or rotate exposed credentials after compromise. See [Kubernetes](k8s.md#configure-the-kubernetes-executor) for the trust boundary, kubeconfig and in-cluster setup, the opt-in namespaced RBAC manifest, exact ownership labels, diagnostics, template rules, and recovery guidance.
|
||||
|
||||
## Sprites.dev
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ Released builds can lag this page. Check **Settings > System > About** or `kande
|
||||
| Profile permissions, CLI flags, literal environment values, and encrypted secret references | Supported | Secret references resolve at launch; a missing/deleted reference omits that variable. Auto-approve and permission-skipping settings enlarge the process trust boundary. |
|
||||
| Local and Worktree executors | Supported | Both are seeded. They execute on the Kandev host; a worktree isolates Git checkouts, not processes, network, credentials, or the rest of the filesystem. |
|
||||
| Local Docker and Sprites executors | Dependency-bound | Require the relevant daemon or provider, compatible host/image, token, platform, and credential-copy configuration. |
|
||||
| Kubernetes executor | Dependency-bound | One session runs in one Pod in an administrator-configured namespace on Linux `amd64` or `arm64`. Launch and recovery require kubeconfig or in-cluster authentication, namespaced Pod RBAC, exec and port-forward streaming, compatible admission and image policy, and storage permissions for the selected workspace mode. Ordinary stops preserve resources; terminal or forced cleanup is UID-, full-identity-, and create-nonce-bound. The experimental matrix validates API and `agentctl` connectivity on Kubernetes 1.34.8 and 1.36.1, with full lifecycle coverage on 1.36.1; other server versions are unvalidated. |
|
||||
| Kubernetes executor | Dependency-bound | Each task uses one Pod shared by its independent sessions in an administrator-configured namespace on Linux `amd64` or `arm64`. Launch and recovery require kubeconfig or in-cluster authentication, namespaced Pod RBAC, exec and port-forward streaming, compatible admission and image policy, and storage permissions for the selected workspace mode. Session stops, including force-stop, preserve task resources; task archive/delete cleanup is UID-, full-identity-, and create-nonce-bound. The experimental matrix validates API and `agentctl` connectivity on Kubernetes 1.34.8 and 1.36.1, with full lifecycle coverage on 1.36.1; other server versions are unvalidated. |
|
||||
| SSH executor | Limited | Remote sessions support trusted Linux or macOS hosts on amd64 or arm64, with public-key authentication, SFTP, and TCP forwarding. The runtime materializes the primary repository at the remote task-workspace root, reuses matching checkouts without resetting local work, runs the resolved prepare hook before `agentctl`, and runs cleanup hooks only for terminal archive/delete stops. Failed preparation blocks launch. Task directories are kept by default; a profile can opt in to **Delete a task's directory when the task is archived or deleted**, which reclaims the remote checkout only on a terminal archive, delete, or cascade delete, and only after the checkout is confirmed to hold no uncommitted changes, unpushed commits, stashes, or ignored files outside Kandev-owned runtime data, and to be shared with no other task. An ordinary stop, a backend shutdown, and a directory that fails any of those checks leave the checkout in place. Password authentication and hostile-user isolation are not provided. |
|
||||
| Remote Docker executor | In progress | The type and legacy/direct settings fields are registered, but runtime create/stop return `not yet implemented`, and the current **Settings > Executors** hub does not offer it. |
|
||||
| GitHub integration | Dependency-bound | Workspace repository scope, issue/PR browsing, actions, watches, presets, reviews, checks, and Gists depend on GitHub auth, scopes, rate limits, and repository permissions. Supported Local Docker, Kubernetes, Sprites, and SSH launch paths may receive the globally stored token as `GITHUB_TOKEN`/`GH_TOKEN`; workspace repository scope does not constrain its privileges. |
|
||||
|
||||
+21
-16
@@ -17,13 +17,13 @@ Kandev ships example Kubernetes YAML in `k8s/`. The control-plane files are a si
|
||||
|
||||
To run task sessions as Pods, follow [Configure the Kubernetes executor](#configure-the-kubernetes-executor) after the control plane is reachable. That is a separate cluster-authority decision.
|
||||
|
||||

|
||||

|
||||
|
||||
[Open full-size SVG diagram][k8s-diagram]
|
||||
|
||||
[k8s-diagram]: ../../docs/screenshots/k8s.svg
|
||||
|
||||
The control-plane Pod owns the persistent home and API identity. Task-session Pods are a separate, opt-in workload path with their own service-account permissions.
|
||||
The control-plane Pod owns the persistent home and API identity. Task Pods are a separate, opt-in workload path with their own service-account permissions.
|
||||
|
||||
## Architecture and limitations
|
||||
|
||||
@@ -36,7 +36,7 @@ The example creates:
|
||||
| `k8s/deployment.yaml` | `Deployment/kandev` | one replica, `Recreate`, example resources and probes |
|
||||
| `k8s/service.yaml` | `Service/kandev` | `ClusterIP`, TCP 38429 |
|
||||
| `k8s/ingress.yaml` | `Ingress/kandev` | ingress-nginx-oriented example for `kandev.example.com` |
|
||||
| `k8s/executor-rbac.yaml` | `ServiceAccount`, `Role`, and `RoleBinding` | Opt-in access for task-session Pods in `kandev-agents`; not part of the deployment quick path |
|
||||
| `k8s/executor-rbac.yaml` | `ServiceAccount`, `Role`, and `RoleBinding` | Opt-in access for task Pods in `kandev-agents`; not part of the deployment quick path |
|
||||
|
||||
One pod serves the SPA, API, WebSocket, external MCP endpoint, and `/health` on port 38429. With SQLite, the same PVC holds the database, workspaces, CLI installs, and authentication files.
|
||||
|
||||
@@ -92,7 +92,9 @@ Open `http://localhost:38429`.
|
||||
|
||||
## Configure the Kubernetes executor
|
||||
|
||||
The Kubernetes executor is independent of where the Kandev control plane runs. A host process can use a kubeconfig, while a Kandev Pod can use either a mounted kubeconfig or its in-cluster service account. One executor connects to one API server context and one namespace; every selected task session gets one Pod in that namespace.
|
||||
The Kubernetes executor is independent of where the Kandev control plane runs. A host process can use a kubeconfig, while a Kandev Pod can use either a mounted kubeconfig or its in-cluster service account. One executor connects to one API server context and one namespace; each task gets one Pod in that namespace. Additional sessions on the same task share that Pod and workspace, with independent agentctl instances and session configuration.
|
||||
|
||||
**A task is one credential trust boundary.** All agents in its Pod run as the same OS user and can read sibling credentials, including credentials from different agent profiles. Separate session HOME directories and configuration prevent accidental mixing; they do not isolate secrets. Attach only mutually trusted agents and credentials. If any sibling is compromised, stop the task's agents and revoke or rotate exposed credentials with their providers. Stopping a session alone does not revoke credentials or undo exposure. Use separate tasks with appropriately isolated executor policies for agents that must not share trust.
|
||||
|
||||
Only administrators can create, edit, delete, or test Kubernetes executors and profiles. Members can list and use administrator-configured profiles, resume their authorized sessions, and view the sanitized status rows available to them. When Kandev authentication is disabled, requests use the synthetic single-user administrator identity.
|
||||
|
||||
@@ -241,12 +243,13 @@ Every Kandev-created Pod and managed PVC has this complete custom identity:
|
||||
|---|---|
|
||||
| `kandev.ai/executor-id` | Executor record ID |
|
||||
| `kandev.ai/profile-id` | Executor-profile record ID |
|
||||
| `kandev.ai/instance-id` | Runtime instance ID |
|
||||
| `kandev.ai/instance-id` | Stable task-environment resource instance ID |
|
||||
| `kandev.ai/task-id` | Task ID |
|
||||
| `kandev.ai/session-id` | Task-session ID |
|
||||
| `kandev.ai/session-id` | Original creating session ID, retained as an immutable provenance label |
|
||||
| `kandev.ai/environment-id` | Task-environment ID |
|
||||
| `kandev.ai/ownership-version` | `task-v1` for new task-owned resources |
|
||||
|
||||
It also owns `app.kubernetes.io/name=kandev-agent`, `app.kubernetes.io/component=agent-session`, `app.kubernetes.io/managed-by=kandev`, and `app.kubernetes.io/instance=<runtime-instance-id>`. All `kandev.ai/*` label and annotation keys are reserved, including keys not listed above. Kandev rejects an admission response that changes or adds one of those reserved identities.
|
||||
It also owns `app.kubernetes.io/name=kandev-agent`, `app.kubernetes.io/component=task-environment`, `app.kubernetes.io/managed-by=kandev`, and `app.kubernetes.io/instance=<task-environment-resource-instance-id>`. All `kandev.ai/*` label and annotation keys are reserved, including keys not listed above. Kandev rejects an admission response that changes or adds one of those reserved identities.
|
||||
|
||||
Every Kandev-created Pod and managed PVC also receives a fresh 256-bit `kandev.ai/create-nonce` annotation for that individual create request. If a create response is lost or ambiguous, Kandev adopts, checkpoints, bootstraps, or deletes the resulting object only when the API object preserves that exact nonce and the complete recorded identity.
|
||||
|
||||
@@ -337,7 +340,7 @@ before use. No production deployment or universal cgroup compatibility is implie
|
||||
|
||||
| Mode | Profile fields | Lifecycle |
|
||||
|---|---|---|
|
||||
| `managed_pvc` | Positive Kubernetes quantity, optional StorageClass, and one or more access modes. Defaults are `10Gi` and `ReadWriteOnce`. | One filesystem PVC per session, without a Pod owner reference. It survives ordinary stop, backend restart, main-container restart, and Pod replacement. Terminal/forced cleanup deletes it only after exact identity verification. |
|
||||
| `managed_pvc` | Positive Kubernetes quantity, optional StorageClass, and one or more access modes. Defaults are `10Gi` and `ReadWriteOnce`. | One filesystem PVC per task, without a Pod owner reference. It survives ordinary stop, backend restart, main-container restart, and Pod replacement. Task archive/delete cleanup deletes it only after exact identity verification. |
|
||||
| `empty_dir` | No PVC fields. | Pod-scoped storage. It survives a container restart but disappears with the Pod. A missing Pod makes the workspace unrecoverable. |
|
||||
| `existing_claim` | Exact claim name in the executor namespace. | Kandev gets and mounts the claim but never creates, relabels, or deletes it. Data retention, access modes, concurrent mounts, and backup remain the operator's responsibility. |
|
||||
|
||||
@@ -345,16 +348,16 @@ A managed claim may remain Pending because of StorageClass, topology, quota, acc
|
||||
|
||||
### Recovery, snapshots, and cleanup
|
||||
|
||||
Kandev's `executors_running` inventory is authoritative. It records exact Pod and PVC namespace/name/UID, full resource identity, workspace ownership, platform, main container, remote port, hashes, and the validated workload launch snapshot. The snapshot contains Pod template, platform, main container, and storage configuration only. It excludes Kandev-resolved credentials, resolved profile environment values, injected files, and scripts; literal values written by an administrator into the Pod template remain in the snapshot.
|
||||
Kandev's `task_environment_kubernetes` inventory is authoritative for task-owned physical resources; `executors_running` records per-session executions and legacy resources. The physical inventory records exact Pod and PVC namespace/name/UID, full resource identity, workspace ownership, platform, main container, remote port, hashes, and the validated workload launch snapshot. The snapshot contains Pod template, platform, main container, and storage configuration only. It excludes Kandev-resolved credentials, resolved profile environment values, injected files, and scripts; literal values written by an administrator into the Pod template remain in the snapshot.
|
||||
|
||||
Current connection configuration and recorded workload configuration serve different purposes:
|
||||
|
||||
- Saved kubeconfig/in-cluster mode, kubeconfig path/context, and timeout are used for later status, reconnect, replacement, and cleanup. Changing credentials or context can restore or break access to an existing session. Retained sessions continue to target their recorded namespace; changing the saved namespace affects new sessions only.
|
||||
- Saved workload profile edits affect new sessions. An existing Pod is never live-mutated, and a missing-Pod replacement uses the recorded workload snapshot rather than the profile's current image, template, platform, main container, or storage fields.
|
||||
- Saved kubeconfig/in-cluster mode, kubeconfig path/context, and timeout are used for later status, reconnect, replacement, and cleanup. Changing credentials or context can restore or break access to an existing session. Retained sessions continue to target their recorded namespace; changing the saved namespace affects new task Pods only.
|
||||
- Saved workload profile edits affect newly provisioned task Pods. Additional sessions reuse the existing task workload snapshot. An existing Pod is never live-mutated, and a missing-Pod replacement uses the recorded workload snapshot rather than the profile's current image, template, platform, main container, or storage fields.
|
||||
|
||||
On resume, Kandev reloads environment definitions from the recorded executor profile and resolves secret references at the launch checkpoint. Changes to that profile's environment can therefore affect a resumed process; they do not rewrite the Pod or storage snapshot. If the profile has been deleted, its environment definitions are unavailable. Profile lookup failures and executor ownership mismatches block resume.
|
||||
|
||||
Ordinary Stop and backend shutdown close local clients and forwards but preserve the Pod and workspace. Agent or main-container restart keeps the Pod volumes; Kandev performs a new nonce handshake and local port-forward. If a Pod disappears, managed or existing PVC storage can support a replacement Pod after identity checks; `emptyDir` cannot.
|
||||
Stop, including force-stop, terminates only the selected session’s agentctl instance and closes its local clients and forwards. Sibling sessions, the Pod, and the workspace remain available. Backend shutdown closes local connections and preserves the remote resources. Agent or main-container restart keeps the Pod volumes; Kandev performs a new nonce handshake and local port-forward. If a Pod disappears, managed or existing PVC storage can support a replacement Pod after identity checks; `emptyDir` cannot.
|
||||
|
||||
A recoverable agent error also preserves the established Pod, workspace, and
|
||||
recovery credentials. Use **Resume** to continue that session. If its retained
|
||||
@@ -362,17 +365,19 @@ credentials or storage are missing, recovery fails rather than silently creating
|
||||
an empty replacement workspace. A software update cannot restore resources that
|
||||
were already deleted.
|
||||
|
||||
Archive/delete terminal cleanup and explicit force cleanup are destructive. Before deletion, Kandev verifies the recorded namespace, name, UID, and complete standard plus `kandev.ai/*` ownership-label set. It then deletes the exact Pod with UID/resource-version preconditions and deletes a PVC only when inventory proves Kandev created that managed claim. Existing claims are never deleted. A missing object is idempotent; an inventory read error, same-name replacement, UID mismatch, missing label, changed label, extra `kandev.ai/*` label, or mismatched create nonce fails closed without deleting the ambiguous object.
|
||||
Task archive/delete cleanup is destructive after all attached sessions are settled. Deleting or stopping an individual session does not delete the task Pod or its managed claim. Before deletion, Kandev verifies the recorded namespace, name, UID, and complete standard plus `kandev.ai/*` ownership-label set. It then deletes the exact Pod with UID/resource-version preconditions and deletes a PVC only when inventory proves Kandev created that managed claim. Existing claims are never deleted. A missing object is idempotent; an inventory read error, same-name replacement, UID mismatch, missing label, changed label, extra `kandev.ai/*` label, or mismatched create nonce fails closed without deleting the ambiguous object.
|
||||
|
||||
Kandev blocks deleting an executor, or changing an executor into or out of Kubernetes, while runtime inventory still refers to it. Finish normal session cleanup first. Profile deletion does not rewrite or destroy a retained workload because recovery owns the recorded profile ID and snapshot.
|
||||
Kandev blocks deleting an executor, or changing an executor into or out of Kubernetes, while runtime inventory still refers to it. Archive or delete the owning tasks to finish resource cleanup first. Removing the last session alone retains the task Pod. Profile deletion does not rewrite or destroy a retained workload because recovery owns the recorded profile ID and snapshot.
|
||||
|
||||
Do not manually delete by name or label alone. If manual incident cleanup is unavoidable, compare the Kandev runtime inventory with namespace, name, UID, and all ownership labels first, preserve required workspace data, and record the out-of-band action.
|
||||
|
||||
Older installations may have several session Pods for one task. Kandev does not merge or delete those Pods automatically. Additional attachment requires an unambiguous recorded Pod and claim with matching task ownership and recoverable credentials; conflicting inventory blocks attachment. Adopted legacy resources keep their original labels.
|
||||
|
||||
### Read retained resource status
|
||||
|
||||
The **Active sessions** card shows the sanitized session inventory for the
|
||||
selected executor. It includes sessions that Kandev can resume after ordinary
|
||||
Stop, not only sessions whose agent process is currently running. The card
|
||||
Stop, not only sessions whose agent process is currently running. A task whose last session has been removed remains listed with its retained Pod and no session ID. Multiple sessions on a task show the same current Pod identity. The card
|
||||
shows separate session state, Pod state, retention state, workspace mode, and
|
||||
main-container CPU and memory requests.
|
||||
|
||||
@@ -511,7 +516,7 @@ Use the SSL mode and trust material required by your database. PostgreSQL moves
|
||||
|
||||
> **Docker boundary:** Do not add only a Docker socket mount. The runtime also needs helper, credential-session, and local-clone bind sources at matching daemon-host paths. Privileged Docker-in-Docker has a separate security and persistence model and no supplied manifest.
|
||||
|
||||
The [Kubernetes executor](#configure-the-kubernetes-executor) creates separate task-session Pods through the Kubernetes API and does not require a Docker socket. The Local and Worktree behavior below instead runs agent processes inside the control-plane Pod itself.
|
||||
The [Kubernetes executor](#configure-the-kubernetes-executor) creates separate task Pods through the Kubernetes API and does not require a Docker socket. The Local and Worktree behavior below instead runs agent processes inside the control-plane Pod itself.
|
||||
|
||||
<details>
|
||||
<summary>Agent execution, resources, and probes</summary>
|
||||
|
||||
@@ -75,9 +75,11 @@ canonical requirement and system-design documents. Use the catalog command to
|
||||
find current sources.
|
||||
|
||||
The [Kubernetes executor foundation](../kubernetes-executor/spec.md) remains
|
||||
the current lifecycle contract. The three Kubernetes pairs own additive
|
||||
presets, launch diagnostics, and retained-compute visibility. They do not
|
||||
replace the foundation's resource ownership, recovery, or cleanup rules.
|
||||
the shipped lifecycle contract. Kubernetes capability pairs extend it. The
|
||||
[task-pod requirements](requirements/kubernetes-task-pod.md) and
|
||||
[design](system-design/kubernetes-task-pod.md) define task-owned compute and
|
||||
replace session ownership. Other foundation
|
||||
security, admission, and recovery guarantees remain applicable.
|
||||
|
||||
## Related systems
|
||||
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
---
|
||||
status: active
|
||||
system: executors
|
||||
created: 2026-09-21
|
||||
owners:
|
||||
- kandev
|
||||
---
|
||||
|
||||
# Kubernetes task pod requirements
|
||||
|
||||
## Overview
|
||||
|
||||
A task's additional Kubernetes sessions share its pod and workspace while
|
||||
retaining independent agent conversations. Executors owns this contract because
|
||||
it governs remote compute ownership. The task system continues to own canonical
|
||||
workspace selection and session identity.
|
||||
|
||||
This contract replaces the session-per-pod rule and concurrent-sharing
|
||||
exclusion in the [foundation](../../kubernetes-executor/spec.md).
|
||||
It implements the user's explicit one-pod-per-task expectation.
|
||||
|
||||
## Requirements
|
||||
|
||||
### REQ-EXECUTORS-KUBERNETES-TASK-POD-001: Task-owned Kubernetes compute
|
||||
|
||||
**Intent:** Starting another agent session must not allocate another task pod.
|
||||
|
||||
#### Acceptance criteria
|
||||
|
||||
- **AC-EXECUTORS-KUBERNETES-TASK-POD-001.1:** When an additional session starts in a task with a ready
|
||||
Kubernetes environment, it shall use the same pod UID and workspace, with an
|
||||
independent agent instance and conversation. Session attachment shall preserve
|
||||
tracked and untracked files without rerunning workspace preparation.
|
||||
- **AC-EXECUTORS-KUBERNETES-TASK-POD-001.2:** When sessions start concurrently, they shall not allocate
|
||||
duplicate task pods or managed workspace claims. An environment still being
|
||||
prepared shall return the existing recoverable preparation error.
|
||||
- **AC-EXECUTORS-KUBERNETES-TASK-POD-001.3:** Stopping, deleting, or failing one session shall not interrupt
|
||||
a sibling's agent, pod, or workspace. A task with no remaining sessions shall
|
||||
retain its environment until task-level cleanup authorizes removal.
|
||||
- **AC-EXECUTORS-KUBERNETES-TASK-POD-001.4:** Backend restart and session resume shall recover the shared
|
||||
recorded pod. Missing-pod recovery shall create at most one replacement for
|
||||
the task, preserve managed workspace data, and retain separate session state.
|
||||
Loss of ephemeral workspace data shall follow the existing explicit recovery
|
||||
failure contract, never silently become a fresh workspace.
|
||||
- **AC-EXECUTORS-KUBERNETES-TASK-POD-001.5:** Final task resource cleanup shall remove only the exactly
|
||||
recorded owned pod and managed claim, after preventing concurrent attachment.
|
||||
Existing administrator-owned claims shall never be deleted.
|
||||
- **AC-EXECUTORS-KUBERNETES-TASK-POD-001.6:** Incompatible executor selection, ambiguous legacy pod inventory,
|
||||
or ownership mismatch shall fail attachment with a recoverable error without
|
||||
creating another pod, adopting foreign resources, or deleting existing data.
|
||||
Existing legacy sessions shall remain resumable under their recorded identity;
|
||||
independent legacy workspaces shall not be merged automatically.
|
||||
- **AC-EXECUTORS-KUBERNETES-TASK-POD-001.7:** Each authorized session's Kubernetes status shall identify its
|
||||
actual shared pod on desktop and mobile. Profile edits shall not mutate the
|
||||
retained task's workload; additional sessions shall use its recorded workload
|
||||
configuration while keeping independent agent-profile runtime settings.
|
||||
|
||||
- **AC-EXECUTORS-KUBERNETES-TASK-POD-001.8:** The task shall be one credential trust boundary.
|
||||
Sessions may use different agent profiles and credentials in the same pod.
|
||||
Per-session settings shall prevent accidental credential inheritance or overwrite,
|
||||
but shall not promise protection from sibling processes running as the same OS user.
|
||||
Operators shall trust every agent attached to a task and manage provider-side
|
||||
credential revocation after suspected exposure.
|
||||
|
||||
## Related contracts
|
||||
|
||||
- [Additional-session workspace reuse](../../tasks/requirements/additional-session-workspace-reuse.md).
|
||||
- [Kubernetes retained compute](kubernetes-retained-compute.md).
|
||||
|
||||
## Out of scope
|
||||
|
||||
Cross-task pod pooling, changing workspace inheritance/group semantics,
|
||||
automatically consolidating legacy pods, concurrent-edit conflict resolution,
|
||||
and redesigning executor UI controls.
|
||||
@@ -0,0 +1,183 @@
|
||||
---
|
||||
status: current
|
||||
system: executors
|
||||
requirements:
|
||||
- REQ-EXECUTORS-KUBERNETES-TASK-POD-001
|
||||
---
|
||||
|
||||
# Kubernetes task pod system design
|
||||
|
||||
## Boundary and evidence
|
||||
|
||||
The executor system owns physical Kubernetes compute; task environments own
|
||||
canonical workspace identity. This design implements
|
||||
[task pod requirements](../requirements/kubernetes-task-pod.md).
|
||||
|
||||
Current `KubernetesExecutor.CreateInstance` locks by `req.InstanceID`, takes the
|
||||
reconnect branch only with recorded pod metadata, and otherwise calls
|
||||
`createFresh`. `newKubernetesFreshLaunch` derives pod/PVC names from that instance
|
||||
ID. `kubernetesIdentity` includes the session ID. Consequently distinct session
|
||||
executions allocate distinct pods even when their task/environment IDs match.
|
||||
`StopInstance` can delete those resources on force/terminal cleanup.
|
||||
|
||||
`connectNewAgentctl` already uses the agentctl control server's `CreateInstance`
|
||||
API. Reuse that multi-instance boundary instead of launching another agentctl
|
||||
server or copying a sibling's execution identity.
|
||||
|
||||
## Requirement mapping
|
||||
|
||||
| Requirement | Implementation boundary |
|
||||
| --- | --- |
|
||||
| `REQ-EXECUTORS-KUBERNETES-TASK-POD-001` | Durable ownership, attach/recovery, cleanup, and projection below |
|
||||
|
||||
## Durable ownership
|
||||
|
||||
Add a typed Kubernetes runtime record associated with the canonical
|
||||
`TaskEnvironment`, separate from `executors_running`. The latter remains the
|
||||
per-session execution inventory; it must not be the sole physical resource owner.
|
||||
Use a dedicated `task_environment_kubernetes` table with environment ID as its
|
||||
primary key and task ID constrained to one canonical Kubernetes runtime record.
|
||||
Do not overload Docker `ContainerID` or its control-secret fields.
|
||||
|
||||
Record executor ID, pinned workload profile/snapshot, environment ownership
|
||||
generation, immutable resource identity, namespace, Pod/PVC names and UIDs,
|
||||
managed-claim ownership, admission checkpoints, create nonce continuity, container
|
||||
restart observation, and encrypted control-token/bootstrap-nonce secret references.
|
||||
No plaintext credential enters this record or a public DTO. Environment deletion
|
||||
must not cascade this inventory before remote cleanup succeeds. The inventory
|
||||
has no cascading environment foreign key: task deletion removes task/environment
|
||||
rows synchronously and durable cleanup runs afterward. Direct environment
|
||||
deletion is guarded while inventory exists. A separate cleanup-only claim can
|
||||
use the retained owner/generation only when both original owner rows are absent;
|
||||
normal launch claims still require a live matching environment.
|
||||
|
||||
Keep resource ownership separate from session identity. New shared resources use
|
||||
an environment-derived stable resource instance identity and a versioned ownership
|
||||
label contract; their authorization must not depend on the current attaching
|
||||
session. Preserve exact legacy ownership labels for adopted legacy resources.
|
||||
Persist the ownership version and validate its complete expected label set plus
|
||||
UIDs. Never relax exact UID checks or create-nonce reconciliation.
|
||||
|
||||
Repository operations claim creation/recovery/deletion with conditional writes
|
||||
against generation and operation identity. Creation and deletion claims are
|
||||
mutually exclusive with attachment. PostgreSQL uses the repository's advisory
|
||||
transaction lock convention; SQLite uses its existing write serialization.
|
||||
Do not hold a database transaction during Kubernetes network calls. Persist each
|
||||
checkpoint before allowing another operation to advance; after restart reconcile
|
||||
the recorded claim and exact create result before retrying allocation. Startup
|
||||
fences interrupted operation revisions under the backend’s existing exclusive
|
||||
runtime-state ownership lock before any worker starts. Incomplete bootstrap
|
||||
inventory without recoverable control credentials blocks attachment and remains
|
||||
available for exact task cleanup.
|
||||
|
||||
## Initial launch and additional attachment
|
||||
|
||||
The canonical environment materializer creates and bootstraps the pod once,
|
||||
persists its control credentials and resource inventory, prepares repositories,
|
||||
and publishes ready only after workspace inventory is complete.
|
||||
|
||||
An additional launch validates task authorization, canonical environment,
|
||||
executor identity, generation and complete repository inventory. Read only the
|
||||
canonical runtime record; a sibling `PreviousExecutionID` is never an attachment
|
||||
handle. Reject a different executor/profile selection that requires changing the
|
||||
retained workload. Editing the same profile does not replace its pinned snapshot.
|
||||
|
||||
Verify the recorded pod, connect to its control server using environment-scoped
|
||||
credentials, and create a new agentctl instance with the new execution/session
|
||||
IDs and canonical workspace. Retain per-instance port-forward/client lifetime.
|
||||
Resolve each agent profile's environment/auth/MCP configuration for that instance;
|
||||
attachment must not rewrite pod-wide runtime/auth files or restart the control
|
||||
server. Audit `buildReconnectCreateInstanceRequest` and bootstrap-file consumers
|
||||
so a new instance does not accidentally inherit another session's agent identity
|
||||
or credentials.
|
||||
|
||||
Attach-only launch skips cloning, repository setup, bootstrap, and pod-level
|
||||
prepare scripts. Preserve current task workspace inheritance admission; this
|
||||
change does not grant cross-task compute sharing when a parent/group environment
|
||||
cannot safely satisfy the task-owned pod boundary. Return typed unsupported reuse
|
||||
rather than silently provisioning a separate workspace.
|
||||
|
||||
A consumed bootstrap handshake retains its issued token until encrypted canonical
|
||||
storage acknowledges it. If that update fails, an environment-derived encrypted
|
||||
recovery secret preserves the token across backend restart; attachment retries
|
||||
finish the canonical save and remove the recovery secret before proceeding.
|
||||
Request cancellation does not cancel the bounded credential persistence attempt.
|
||||
Task teardown also removes the recovery secret.
|
||||
|
||||
## Credential trust boundary
|
||||
|
||||
The task is one trust boundary, as recorded in the
|
||||
[credential trust ADR](../../../decisions/2026-09-23-kubernetes-task-trust-boundary.md).
|
||||
Different agent profiles and credential bindings are allowed within its pod.
|
||||
Per-session HOME, environment and auth files separate configuration; all agents
|
||||
run as the same OS user and can read sibling files and process credentials.
|
||||
File permissions and hashed session paths do not provide security isolation.
|
||||
|
||||
Operators must attach only mutually trusted agents and credentials. After a
|
||||
suspected compromise, stop the task's agents and revoke or rotate exposed
|
||||
credentials with their providers; stopping one session cannot undo exposure.
|
||||
Use separate tasks with appropriately isolated executor policies when agents
|
||||
must not share trust. Regression coverage verifies distinct profiles and
|
||||
credentials use one pod without overwriting each other's launch settings.
|
||||
|
||||
## Session termination and task cleanup
|
||||
|
||||
Session stop/delete terminates only that agentctl instance and its local
|
||||
connections. Force is not authority to delete the task's resources. Failed
|
||||
attachment rolls back only resources allocated by that attachment.
|
||||
|
||||
Task archive/delete resource cleanup claims the environment for deletion, blocks
|
||||
new attachment, settles all attached executions through the existing task cleanup
|
||||
orchestrator, and verifies that no execution still needs the resource. One stopped
|
||||
or failed row is insufficient when any sibling is live. Run cleanup scripts from task teardown rather than individual session stops,
|
||||
then perform exact-UID/ownership-checked Pod and managed-PVC deletion.
|
||||
Retain inventory and credentials for retry on partial deletion failure. External
|
||||
claims are never deleted. Zero-session environments remain discoverable for
|
||||
retention/status and terminal cleanup.
|
||||
|
||||
## Recovery and compatibility
|
||||
|
||||
Backend restart reconstructs environment control connections independently of
|
||||
session connections. A single generation claim owns missing-pod replacement from
|
||||
the pinned launch snapshot and existing managed PVC. Other resumes wait or return
|
||||
a recoverable preparing result; they cannot provision replacements independently.
|
||||
A pod/container restart invalidates all affected per-instance clients; refresh
|
||||
projects the same physical generation while each session reconnects independently.
|
||||
|
||||
Migration is additive and non-destructive. At first use, adopt legacy inventory
|
||||
only when all relevant retained rows agree on one exact pod/PVC identity, matching
|
||||
canonical task/environment ownership, and available encrypted control credentials.
|
||||
Preserve legacy resource labels and record the ownership version. Multiple pods,
|
||||
conflicting snapshots, missing identity, or unreadable inventory block additional
|
||||
attachment. Existing recorded legacy sessions retain their current resume/cleanup
|
||||
path; do not rewrite their files, move claims, or delete a supposed duplicate.
|
||||
|
||||
An explicitly selected executor transition must use the existing task environment
|
||||
transition contract and cannot attach to stale Kubernetes state. This work does
|
||||
not add automatic executor migration.
|
||||
|
||||
## Status and diagnostics
|
||||
|
||||
`internal/kubernetes/sessions.go` keeps authorized session rows but resolves shared
|
||||
physical identity through their canonical runtime record. Probe each exact pod
|
||||
once per request and project its result to authorized rows; session counts remain
|
||||
session counts. Retained environment visibility must survive removal of its last
|
||||
session. Never expose control secrets. Existing desktop/mobile components consume
|
||||
the same response shape, so this package introduces no layout or control changes.
|
||||
Log task/environment and execution identifiers for attach/create/recover/delete
|
||||
operations and bounded failure categories, without credential payloads.
|
||||
|
||||
## Verification
|
||||
|
||||
Use fake Kubernetes clients through real lifecycle entry points for two-session
|
||||
attachment, concurrent launch/recovery, stop-one/sibling-live, forced session
|
||||
cleanup, failed attachment rollback, task cleanup, retained zero-session state,
|
||||
profile snapshot pinning, per-instance env isolation, and foreign UID rejection.
|
||||
Repository tests cover claim exclusion, replay, and mixed legacy inventories.
|
||||
Kind E2E starts two real sessions, observes one Pod/PVC and distinct instances,
|
||||
checks an untracked file from both, stops one, restarts the backend, resumes, then
|
||||
archives the task and checks cleanup. No production cluster reproduction is needed.
|
||||
|
||||
## Related decisions
|
||||
|
||||
[Task-owned Kubernetes compute](../../../decisions/2026-09-21-kubernetes-task-pod-ownership.md).
|
||||
@@ -7,6 +7,12 @@ owner: Kandev
|
||||
|
||||
# Kubernetes Executor
|
||||
|
||||
## Ownership transition
|
||||
|
||||
This file records the Kubernetes foundation. The
|
||||
[task-pod contract](../executors/requirements/kubernetes-task-pod.md) and
|
||||
[design](../executors/system-design/kubernetes-task-pod.md) own the task-shared Pod lifecycle; the remaining foundation stays in force.
|
||||
|
||||
## Why
|
||||
|
||||
Teams that already operate Kubernetes need Kandev sessions to run inside their
|
||||
@@ -25,7 +31,7 @@ first-class Pod with an administrator-reviewed workload template.
|
||||
- Administrators can create Kubernetes profiles from one strict
|
||||
`core/v1 PodTemplate` YAML document. The profile chooses the main container,
|
||||
Linux architecture, and workspace storage policy.
|
||||
- One task session maps to one Pod. Kandev starts its existing `agentctl`
|
||||
- One task maps to one Pod shared by its independent sessions. Kandev starts its existing `agentctl`
|
||||
control process in the designated container and reaches it through a
|
||||
loopback-only Kubernetes port-forward.
|
||||
- The template can define images, sidecars, init containers, resource and
|
||||
@@ -36,11 +42,11 @@ first-class Pod with an administrator-reviewed workload template.
|
||||
`kandev-workspace` mount at exactly `/workspace`; admission must preserve
|
||||
its recipient and shape. Runtime/auth mounts and init/ephemeral containers
|
||||
remain excluded. See [workspace grants](../executors/system-design/kubernetes-docker-workloads.md).
|
||||
- Profiles support a Kandev-managed per-session PVC, a Pod-scoped `emptyDir`,
|
||||
- Profiles support a Kandev-managed per-task PVC, a Pod-scoped `emptyDir`,
|
||||
or an existing namespaced PVC. Kandev never deletes an existing PVC.
|
||||
- Ordinary Stop and backend shutdown preserve the Pod and workspace for
|
||||
resume. Archive, delete, and explicit force cleanup remove only resources
|
||||
proven to belong to the recorded session.
|
||||
resume. Session stop/delete removes only its agentctl instance. Task archive/delete
|
||||
removes only resources proven to belong to the canonical task environment.
|
||||
- Members can discover and use administrator-configured Kubernetes profiles.
|
||||
They cannot create, edit, delete, or test Kubernetes executor/profile
|
||||
configuration.
|
||||
@@ -193,7 +199,7 @@ or cluster-resource identity.
|
||||
agent subprocess.
|
||||
6. **Preserved:** ordinary stop or backend shutdown closes local forwarding but
|
||||
retains Pod/workspace for resume.
|
||||
7. **Cleaning:** terminal/forced cleanup validates exact identities, deletes
|
||||
7. **Cleaning:** task archive/delete cleanup validates exact identities, deletes
|
||||
the Pod, then deletes only a Kandev-created PVC.
|
||||
8. **Cleaned:** resources are absent and runtime inventory can be removed.
|
||||
|
||||
@@ -356,7 +362,7 @@ identity check or inventory lookup stops cleanup without deleting anything.
|
||||
sessions, autoscaling, and pooled/multi-cluster scheduling.
|
||||
- Cross-namespace profiles inside one executor.
|
||||
- Windows Pods and automatic node-architecture discovery.
|
||||
- Sharing one Pod or one managed PVC among concurrent sessions.
|
||||
- Sharing one Pod or one managed PVC among different tasks.
|
||||
- Live mutation of running Pods after profile edits.
|
||||
- Raw kubeconfig storage in executor JSON or the current user-scoped secret
|
||||
store.
|
||||
|
||||
Reference in New Issue
Block a user