diff --git a/workspace-server/internal/handlers/workspace_provision.go b/workspace-server/internal/handlers/workspace_provision.go index e3e95887b..0f3b8fd08 100644 --- a/workspace-server/internal/handlers/workspace_provision.go +++ b/workspace-server/internal/handlers/workspace_provision.go @@ -2,6 +2,7 @@ package handlers import ( "context" + "database/sql" "fmt" "log" "os" @@ -328,6 +329,8 @@ func (h *WorkspaceHandler) buildProvisionerConfig( workspaceAccess = dbAccess } kind = dbKind + } else if err != sql.ErrNoRows { + log.Printf("ERROR: workspace kind lookup failed for %s: %v", workspaceID, err) } } if workspacePath == "" { diff --git a/workspace-server/internal/provisioner/cp_provisioner.go b/workspace-server/internal/provisioner/cp_provisioner.go index aa558fe70..ca87f659c 100644 --- a/workspace-server/internal/provisioner/cp_provisioner.go +++ b/workspace-server/internal/provisioner/cp_provisioner.go @@ -262,6 +262,15 @@ func (p *CPProvisioner) Start(ctx context.Context, cfg WorkspaceConfig) (string, return "", fmt.Errorf("cp provisioner: collect config files: %w", err) } + // Only forward kind for platform workspaces; omitempty hides it for ordinary + // workspaces so the wire shape is unchanged and older CPs see byte-identical + // requests. Ordinary workspaces always have kind="workspace" from the DB + // COALESCE, so we must explicitly suppress it here (core#2498 truth-up). + kind := "" + if cfg.Kind == WorkspaceKindPlatform { + kind = cfg.Kind + } + req := cpProvisionRequest{ OrgID: p.orgID, WorkspaceID: cfg.WorkspaceID, @@ -271,7 +280,7 @@ func (p *CPProvisioner) Start(ctx context.Context, cfg WorkspaceConfig) (string, DiskGB: cfg.DiskGB, DataPersistence: cfg.DataPersistence, Provider: cfg.Provider, - Kind: cfg.Kind, + Kind: kind, Display: cfg.Display, PlatformURL: cfg.PlatformURL, Env: env, diff --git a/workspace-server/internal/provisioner/cp_provisioner_kind_test.go b/workspace-server/internal/provisioner/cp_provisioner_kind_test.go index 20601c795..62670e252 100644 --- a/workspace-server/internal/provisioner/cp_provisioner_kind_test.go +++ b/workspace-server/internal/provisioner/cp_provisioner_kind_test.go @@ -63,9 +63,13 @@ func TestStart_ForwardsPlatformKind(t *testing.T) { // CPs see byte-identical requests. func TestStart_OmitsKindForOrdinaryWorkspace(t *testing.T) { p, body := startCaptureCP(t) + // Ordinary workspaces have kind="workspace" from the DB COALESCE; + // the CP provisioner must suppress it so omitempty keeps the wire + // shape unchanged (core#2498 truth-up). _, err := p.Start(context.Background(), WorkspaceConfig{ WorkspaceID: "ws-ordinary", Runtime: "claude-code", + Kind: "workspace", PlatformURL: "https://acme.example.com", }) if err != nil {