zenml-nightly 0.75.0.dev20250313__py3-none-any.whl → 0.75.0.dev20250314__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. zenml/VERSION +1 -1
  2. zenml/analytics/context.py +4 -4
  3. zenml/analytics/enums.py +2 -2
  4. zenml/artifacts/utils.py +2 -2
  5. zenml/cli/__init__.py +8 -9
  6. zenml/cli/base.py +2 -2
  7. zenml/cli/code_repository.py +1 -1
  8. zenml/cli/pipeline.py +3 -3
  9. zenml/cli/project.py +172 -0
  10. zenml/cli/service_accounts.py +0 -1
  11. zenml/cli/service_connectors.py +15 -16
  12. zenml/cli/stack.py +0 -2
  13. zenml/cli/stack_components.py +2 -2
  14. zenml/cli/utils.py +3 -3
  15. zenml/client.py +347 -340
  16. zenml/config/global_config.py +41 -43
  17. zenml/constants.py +5 -3
  18. zenml/event_hub/event_hub.py +1 -1
  19. zenml/integrations/gcp/service_connectors/gcp_service_connector.py +7 -6
  20. zenml/integrations/mlflow/steps/mlflow_registry.py +3 -3
  21. zenml/integrations/wandb/__init__.py +1 -1
  22. zenml/integrations/wandb/experiment_trackers/wandb_experiment_tracker.py +29 -9
  23. zenml/integrations/wandb/flavors/wandb_experiment_tracker_flavor.py +2 -0
  24. zenml/model/model.py +2 -2
  25. zenml/model_registries/base_model_registry.py +1 -1
  26. zenml/models/__init__.py +29 -29
  27. zenml/models/v2/base/filter.py +1 -1
  28. zenml/models/v2/base/scoped.py +49 -53
  29. zenml/models/v2/core/action.py +12 -12
  30. zenml/models/v2/core/artifact.py +15 -15
  31. zenml/models/v2/core/artifact_version.py +15 -15
  32. zenml/models/v2/core/code_repository.py +12 -12
  33. zenml/models/v2/core/event_source.py +12 -12
  34. zenml/models/v2/core/model.py +17 -17
  35. zenml/models/v2/core/model_version.py +15 -15
  36. zenml/models/v2/core/pipeline.py +15 -15
  37. zenml/models/v2/core/pipeline_build.py +14 -14
  38. zenml/models/v2/core/pipeline_deployment.py +12 -14
  39. zenml/models/v2/core/pipeline_run.py +16 -16
  40. zenml/models/v2/core/project.py +203 -0
  41. zenml/models/v2/core/run_metadata.py +2 -2
  42. zenml/models/v2/core/run_template.py +15 -15
  43. zenml/models/v2/core/schedule.py +12 -12
  44. zenml/models/v2/core/secret.py +1 -1
  45. zenml/models/v2/core/service.py +14 -14
  46. zenml/models/v2/core/step_run.py +13 -13
  47. zenml/models/v2/core/trigger.py +13 -13
  48. zenml/models/v2/core/trigger_execution.py +2 -2
  49. zenml/models/v2/core/user.py +0 -17
  50. zenml/models/v2/misc/statistics.py +4 -4
  51. zenml/orchestrators/cache_utils.py +7 -7
  52. zenml/orchestrators/input_utils.py +1 -1
  53. zenml/orchestrators/step_launcher.py +1 -1
  54. zenml/orchestrators/step_run_utils.py +2 -2
  55. zenml/orchestrators/utils.py +4 -4
  56. zenml/pipelines/build_utils.py +2 -2
  57. zenml/pipelines/pipeline_definition.py +5 -5
  58. zenml/pipelines/run_utils.py +1 -1
  59. zenml/service_connectors/service_connector.py +0 -3
  60. zenml/service_connectors/service_connector_utils.py +0 -1
  61. zenml/stack/stack.py +0 -1
  62. zenml/steps/base_step.py +10 -2
  63. zenml/zen_server/rbac/endpoint_utils.py +17 -17
  64. zenml/zen_server/rbac/models.py +20 -20
  65. zenml/zen_server/rbac/rbac_sql_zen_store.py +3 -3
  66. zenml/zen_server/rbac/utils.py +23 -25
  67. zenml/zen_server/rbac/zenml_cloud_rbac.py +12 -16
  68. zenml/zen_server/routers/artifact_version_endpoints.py +10 -10
  69. zenml/zen_server/routers/auth_endpoints.py +6 -6
  70. zenml/zen_server/routers/code_repositories_endpoints.py +12 -14
  71. zenml/zen_server/routers/model_versions_endpoints.py +13 -15
  72. zenml/zen_server/routers/models_endpoints.py +7 -9
  73. zenml/zen_server/routers/pipeline_builds_endpoints.py +14 -16
  74. zenml/zen_server/routers/pipeline_deployments_endpoints.py +13 -15
  75. zenml/zen_server/routers/pipelines_endpoints.py +16 -18
  76. zenml/zen_server/routers/{workspaces_endpoints.py → projects_endpoints.py} +111 -68
  77. zenml/zen_server/routers/run_metadata_endpoints.py +7 -9
  78. zenml/zen_server/routers/run_templates_endpoints.py +15 -17
  79. zenml/zen_server/routers/runs_endpoints.py +12 -14
  80. zenml/zen_server/routers/schedule_endpoints.py +12 -14
  81. zenml/zen_server/routers/secrets_endpoints.py +1 -3
  82. zenml/zen_server/routers/server_endpoints.py +5 -5
  83. zenml/zen_server/routers/service_connectors_endpoints.py +11 -13
  84. zenml/zen_server/routers/service_endpoints.py +7 -9
  85. zenml/zen_server/routers/stack_components_endpoints.py +9 -11
  86. zenml/zen_server/routers/stacks_endpoints.py +9 -11
  87. zenml/zen_server/routers/steps_endpoints.py +6 -6
  88. zenml/zen_server/routers/users_endpoints.py +5 -43
  89. zenml/zen_server/template_execution/utils.py +4 -4
  90. zenml/zen_server/utils.py +10 -10
  91. zenml/zen_server/zen_server_api.py +3 -2
  92. zenml/zen_stores/base_zen_store.py +35 -39
  93. zenml/zen_stores/migrations/versions/12eff0206201_rename_workspace_to_project.py +768 -0
  94. zenml/zen_stores/migrations/versions/41b28cae31ce_make_artifacts_workspace_scoped.py +3 -3
  95. zenml/zen_stores/migrations/versions/cbc6acd71f92_add_workspace_display_name.py +58 -0
  96. zenml/zen_stores/rest_zen_store.py +54 -62
  97. zenml/zen_stores/schemas/__init__.py +2 -2
  98. zenml/zen_stores/schemas/action_schemas.py +9 -9
  99. zenml/zen_stores/schemas/artifact_schemas.py +15 -17
  100. zenml/zen_stores/schemas/code_repository_schemas.py +16 -18
  101. zenml/zen_stores/schemas/event_source_schemas.py +9 -9
  102. zenml/zen_stores/schemas/model_schemas.py +15 -17
  103. zenml/zen_stores/schemas/pipeline_build_schemas.py +7 -7
  104. zenml/zen_stores/schemas/pipeline_deployment_schemas.py +7 -7
  105. zenml/zen_stores/schemas/pipeline_run_schemas.py +9 -9
  106. zenml/zen_stores/schemas/pipeline_schemas.py +9 -9
  107. zenml/zen_stores/schemas/{workspace_schemas.py → project_schemas.py} +47 -41
  108. zenml/zen_stores/schemas/run_metadata_schemas.py +5 -5
  109. zenml/zen_stores/schemas/run_template_schemas.py +9 -9
  110. zenml/zen_stores/schemas/schedule_schema.py +9 -9
  111. zenml/zen_stores/schemas/service_schemas.py +7 -7
  112. zenml/zen_stores/schemas/step_run_schemas.py +7 -7
  113. zenml/zen_stores/schemas/trigger_schemas.py +9 -9
  114. zenml/zen_stores/schemas/user_schemas.py +0 -12
  115. zenml/zen_stores/sql_zen_store.py +258 -268
  116. zenml/zen_stores/zen_store_interface.py +56 -70
  117. {zenml_nightly-0.75.0.dev20250313.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/METADATA +1 -1
  118. {zenml_nightly-0.75.0.dev20250313.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/RECORD +121 -119
  119. zenml/cli/workspace.py +0 -160
  120. zenml/models/v2/core/workspace.py +0 -131
  121. {zenml_nightly-0.75.0.dev20250313.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/LICENSE +0 -0
  122. {zenml_nightly-0.75.0.dev20250313.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/WHEEL +0 -0
  123. {zenml_nightly-0.75.0.dev20250313.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/entry_points.txt +0 -0
@@ -20,8 +20,8 @@ from zenml.models.v2.base.base import (
20
20
  )
21
21
 
22
22
 
23
- class WorkspaceStatistics(BaseZenModel):
24
- """Workspace statistics."""
23
+ class ProjectStatistics(BaseZenModel):
24
+ """Project statistics."""
25
25
 
26
26
  pipelines: int = Field(
27
27
  title="The number of pipelines.",
@@ -40,6 +40,6 @@ class ServerStatistics(BaseZenModel):
40
40
  components: int = Field(
41
41
  title="The number of components.",
42
42
  )
43
- workspaces: int = Field(
44
- title="The number of workspaces.",
43
+ projects: int = Field(
44
+ title="The number of projects.",
45
45
  )
@@ -34,7 +34,7 @@ def generate_cache_key(
34
34
  step: "Step",
35
35
  input_artifact_ids: Dict[str, "UUID"],
36
36
  artifact_store: "BaseArtifactStore",
37
- workspace_id: "UUID",
37
+ project_id: "UUID",
38
38
  ) -> str:
39
39
  """Generates a cache key for a step run.
40
40
 
@@ -42,7 +42,7 @@ def generate_cache_key(
42
42
  runs are identical and can be cached.
43
43
 
44
44
  The cache key is a MD5 hash of:
45
- - the workspace ID,
45
+ - the project ID,
46
46
  - the artifact store ID and path,
47
47
  - the source code that defines the step,
48
48
  - the parameters of the step,
@@ -55,15 +55,15 @@ def generate_cache_key(
55
55
  step: The step to generate the cache key for.
56
56
  input_artifact_ids: The input artifact IDs for the step.
57
57
  artifact_store: The artifact store of the active stack.
58
- workspace_id: The ID of the active workspace.
58
+ project_id: The ID of the active project.
59
59
 
60
60
  Returns:
61
61
  A cache key.
62
62
  """
63
63
  hash_ = hashlib.md5() # nosec
64
64
 
65
- # Workspace ID
66
- hash_.update(workspace_id.bytes)
65
+ # Project ID
66
+ hash_.update(project_id.bytes)
67
67
 
68
68
  # Artifact store ID and path
69
69
  hash_.update(artifact_store.id.bytes)
@@ -106,7 +106,7 @@ def get_cached_step_run(cache_key: str) -> Optional["StepRunResponse"]:
106
106
  """If a given step can be cached, get the corresponding existing step run.
107
107
 
108
108
  A step run can be cached if there is an existing step run in the same
109
- workspace which has the same cache key and was successfully executed.
109
+ project which has the same cache key and was successfully executed.
110
110
 
111
111
  Args:
112
112
  cache_key: The cache key of the step.
@@ -117,7 +117,7 @@ def get_cached_step_run(cache_key: str) -> Optional["StepRunResponse"]:
117
117
  client = Client()
118
118
 
119
119
  cache_candidates = client.list_run_steps(
120
- workspace=client.active_workspace.id,
120
+ project=client.active_project.id,
121
121
  cache_key=cache_key,
122
122
  status=ExecutionStatus.COMPLETED,
123
123
  sort_by=f"{SorterOps.DESCENDING}:created",
@@ -55,7 +55,7 @@ def resolve_step_inputs(
55
55
  for run_step in pagination_utils.depaginate(
56
56
  Client().list_run_steps,
57
57
  pipeline_run_id=pipeline_run.id,
58
- workspace=pipeline_run.workspace.id,
58
+ project=pipeline_run.project.id,
59
59
  )
60
60
  }
61
61
 
@@ -319,7 +319,7 @@ class StepLauncher:
319
319
  pipeline_run = PipelineRunRequest(
320
320
  name=run_name,
321
321
  orchestrator_run_id=self._orchestrator_run_id,
322
- workspace=client.active_workspace.id,
322
+ project=client.active_project.id,
323
323
  deployment=self._deployment.id,
324
324
  pipeline=(
325
325
  self._deployment.pipeline.id
@@ -75,7 +75,7 @@ class StepRunRequestFactory:
75
75
  pipeline_run_id=self.pipeline_run.id,
76
76
  status=ExecutionStatus.RUNNING,
77
77
  start_time=utc_now(),
78
- workspace=Client().active_workspace.id,
78
+ project=Client().active_project.id,
79
79
  )
80
80
 
81
81
  def populate_request(self, request: StepRunRequest) -> None:
@@ -102,7 +102,7 @@ class StepRunRequestFactory:
102
102
  step=step,
103
103
  input_artifact_ids=input_artifact_ids,
104
104
  artifact_store=self.stack.artifact_store,
105
- workspace_id=Client().active_workspace.id,
105
+ project_id=Client().active_project.id,
106
106
  )
107
107
  request.cache_key = cache_key
108
108
 
@@ -23,8 +23,8 @@ from zenml.config.global_config import (
23
23
  GlobalConfiguration,
24
24
  )
25
25
  from zenml.constants import (
26
+ ENV_ZENML_ACTIVE_PROJECT_ID,
26
27
  ENV_ZENML_ACTIVE_STACK_ID,
27
- ENV_ZENML_ACTIVE_WORKSPACE_ID,
28
28
  ENV_ZENML_DISABLE_CREDENTIALS_DISK_CACHING,
29
29
  ENV_ZENML_PIPELINE_RUN_API_TOKEN_EXPIRATION,
30
30
  ENV_ZENML_SERVER,
@@ -211,13 +211,13 @@ def get_config_environment_vars(
211
211
  # in the pipeline run environment
212
212
  environment_vars[ENV_ZENML_DISABLE_CREDENTIALS_DISK_CACHING] = "true"
213
213
 
214
- # Make sure to use the correct active stack/workspace which might come
214
+ # Make sure to use the correct active stack/project which might come
215
215
  # from a .zen repository and not the global config
216
216
  environment_vars[ENV_ZENML_ACTIVE_STACK_ID] = str(
217
217
  Client().active_stack_model.id
218
218
  )
219
- environment_vars[ENV_ZENML_ACTIVE_WORKSPACE_ID] = str(
220
- Client().active_workspace.id
219
+ environment_vars[ENV_ZENML_ACTIVE_PROJECT_ID] = str(
220
+ Client().active_project.id
221
221
  )
222
222
 
223
223
  return environment_vars
@@ -215,7 +215,7 @@ def reuse_or_create_pipeline_build(
215
215
  build_model = Client().zen_store.get_build(build_id=build)
216
216
  else:
217
217
  build_request = PipelineBuildRequest(
218
- workspace=Client().active_workspace.id,
218
+ project=Client().active_project.id,
219
219
  stack=Client().active_stack_model.id,
220
220
  pipeline=pipeline_id,
221
221
  **build.model_dump(),
@@ -418,7 +418,7 @@ def create_pipeline_build(
418
418
  )
419
419
  stack_checksum = compute_stack_checksum(stack=stack_model)
420
420
  build_request = PipelineBuildRequest(
421
- workspace=client.active_workspace.id,
421
+ project=client.active_project.id,
422
422
  stack=stack_model.id,
423
423
  pipeline=pipeline_id,
424
424
  is_local=is_local,
@@ -684,7 +684,7 @@ To avoid this consider setting pipeline parameters only in one place (config or
684
684
  components = Client().active_stack_model.components
685
685
  orchestrator = components[StackComponentType.ORCHESTRATOR][0]
686
686
  schedule_model = ScheduleRequest(
687
- workspace=Client().active_workspace.id,
687
+ project=Client().active_project.id,
688
688
  pipeline_id=pipeline_id,
689
689
  orchestrator_id=orchestrator.id,
690
690
  name=schedule_name,
@@ -770,7 +770,7 @@ To avoid this consider setting pipeline parameters only in one place (config or
770
770
  code_path = code_utils.upload_code_if_necessary(code_archive)
771
771
 
772
772
  request = PipelineDeploymentRequest(
773
- workspace=Client().active_workspace.id,
773
+ project=Client().active_project.id,
774
774
  stack=stack.id,
775
775
  pipeline=pipeline_id,
776
776
  build=build_id,
@@ -1013,7 +1013,7 @@ To avoid this consider setting pipeline parameters only in one place (config or
1013
1013
  for component_type, component in stack.components.items()
1014
1014
  }
1015
1015
  return {
1016
- "workspace_id": deployment.workspace.id,
1016
+ "project_id": deployment.project.id,
1017
1017
  "store_type": Client().zen_store.type.value,
1018
1018
  **stack_metadata,
1019
1019
  "total_steps": len(self.invocations),
@@ -1094,7 +1094,7 @@ To avoid this consider setting pipeline parameters only in one place (config or
1094
1094
  return _get()
1095
1095
  except RuntimeError:
1096
1096
  request = PipelineRequest(
1097
- workspace=client.active_workspace.id,
1097
+ project=client.active_project.id,
1098
1098
  name=self.name,
1099
1099
  )
1100
1100
 
@@ -1233,7 +1233,7 @@ To avoid this consider setting pipeline parameters only in one place (config or
1233
1233
  return id_
1234
1234
 
1235
1235
  if not allow_suffix:
1236
- raise RuntimeError("Duplicate step ID")
1236
+ raise RuntimeError(f"Duplicate step ID `{id_}`")
1237
1237
 
1238
1238
  for index in range(2, 10000):
1239
1239
  id_ = f"{base_id}_{index}"
@@ -81,7 +81,7 @@ def create_placeholder_run(
81
81
  # running.
82
82
  start_time=start_time,
83
83
  orchestrator_run_id=None,
84
- workspace=deployment.workspace.id,
84
+ project=deployment.project.id,
85
85
  deployment=deployment.id,
86
86
  pipeline=deployment.pipeline.id if deployment.pipeline else None,
87
87
  status=ExecutionStatus.INITIALIZING,
@@ -705,7 +705,6 @@ class ServiceConnector(BaseModel, metaclass=ServiceConnectorMeta):
705
705
 
706
706
  def to_model(
707
707
  self,
708
- workspace: UUID,
709
708
  name: Optional[str] = None,
710
709
  description: str = "",
711
710
  labels: Optional[Dict[str, str]] = None,
@@ -714,7 +713,6 @@ class ServiceConnector(BaseModel, metaclass=ServiceConnectorMeta):
714
713
 
715
714
  Args:
716
715
  name: The name of the connector.
717
- workspace: The ID of the workspace that the connector belongs to.
718
716
  description: The description of the connector.
719
717
  labels: The labels of the connector.
720
718
 
@@ -737,7 +735,6 @@ class ServiceConnector(BaseModel, metaclass=ServiceConnectorMeta):
737
735
  connector_type=spec.connector_type,
738
736
  name=name,
739
737
  description=description,
740
- workspace=workspace,
741
738
  auth_method=self.auth_method,
742
739
  expires_at=self.expires_at,
743
740
  expires_skew_tolerance=self.expires_skew_tolerance,
@@ -184,7 +184,6 @@ def get_resources_options_from_resource_model_for_full_stack(
184
184
  else:
185
185
  resource_model = zen_store.verify_service_connector_config(
186
186
  service_connector=ServiceConnectorRequest(
187
- workspace=client.active_workspace.id,
188
187
  name="fake",
189
188
  connector_type=connector_details.type,
190
189
  auth_method=connector_details.auth_method,
zenml/stack/stack.py CHANGED
@@ -756,7 +756,6 @@ class Stack:
756
756
  type=flavor.type,
757
757
  config=LocalImageBuilderConfig(),
758
758
  user=Client().active_user.id,
759
- workspace=Client().active_workspace.id,
760
759
  created=now,
761
760
  updated=now,
762
761
  )
zenml/steps/base_step.py CHANGED
@@ -432,7 +432,9 @@ class BaseStep:
432
432
  self,
433
433
  *args: Any,
434
434
  id: Optional[str] = None,
435
- after: Union[str, Sequence[str], None] = None,
435
+ after: Union[
436
+ str, StepArtifact, Sequence[Union[str, StepArtifact]], None
437
+ ] = None,
436
438
  **kwargs: Any,
437
439
  ) -> Any:
438
440
  """Handle a call of the step.
@@ -497,8 +499,14 @@ class BaseStep:
497
499
  }
498
500
  if isinstance(after, str):
499
501
  upstream_steps.add(after)
502
+ elif isinstance(after, StepArtifact):
503
+ upstream_steps.add(after.invocation_id)
500
504
  elif isinstance(after, Sequence):
501
- upstream_steps = upstream_steps.union(after)
505
+ for item in after:
506
+ if isinstance(item, str):
507
+ upstream_steps.add(item)
508
+ elif isinstance(item, StepArtifact):
509
+ upstream_steps.add(item.invocation_id)
502
510
 
503
511
  invocation_id = Pipeline.ACTIVE_PIPELINE.add_step_invocation(
504
512
  step=self,
@@ -22,8 +22,8 @@ from zenml.models import (
22
22
  BaseRequest,
23
23
  BaseUpdate,
24
24
  Page,
25
+ ProjectScopedFilter,
25
26
  UserScopedRequest,
26
- WorkspaceScopedFilter,
27
27
  )
28
28
  from zenml.zen_server.auth import get_auth_context
29
29
  from zenml.zen_server.feature_gate.endpoint_utils import (
@@ -42,7 +42,7 @@ from zenml.zen_server.rbac.utils import (
42
42
  verify_permission,
43
43
  verify_permission_for_model,
44
44
  )
45
- from zenml.zen_server.utils import server_config, set_filter_workspace_scope
45
+ from zenml.zen_server.utils import server_config, set_filter_project_scope
46
46
 
47
47
  AnyRequest = TypeVar("AnyRequest", bound=BaseRequest)
48
48
  AnyResponse = TypeVar("AnyResponse", bound=BaseIdentifiedResponse) # type: ignore[type-arg]
@@ -232,27 +232,27 @@ def verify_permissions_and_list_entities(
232
232
  A page of entity models.
233
233
 
234
234
  Raises:
235
- ValueError: If the filter's workspace scope is not set or is not a UUID.
235
+ ValueError: If the filter's project scope is not set or is not a UUID.
236
236
  """
237
237
  auth_context = get_auth_context()
238
238
  assert auth_context
239
239
 
240
- workspace_id: Optional[UUID] = None
241
- if isinstance(filter_model, WorkspaceScopedFilter):
242
- # A workspace scoped filter must always be scoped to a specific
243
- # workspace. This is required for the RBAC check to work.
244
- set_filter_workspace_scope(filter_model)
245
- if not filter_model.workspace or not isinstance(
246
- filter_model.workspace, UUID
240
+ project_id: Optional[UUID] = None
241
+ if isinstance(filter_model, ProjectScopedFilter):
242
+ # A project scoped filter must always be scoped to a specific
243
+ # project. This is required for the RBAC check to work.
244
+ set_filter_project_scope(filter_model)
245
+ if not filter_model.project or not isinstance(
246
+ filter_model.project, UUID
247
247
  ):
248
248
  raise ValueError(
249
- "Workspace scope must be a UUID, got "
250
- f"{type(filter_model.workspace)}."
249
+ "Project scope must be a UUID, got "
250
+ f"{type(filter_model.project)}."
251
251
  )
252
- workspace_id = filter_model.workspace
252
+ project_id = filter_model.project
253
253
 
254
254
  allowed_ids = get_allowed_resource_ids(
255
- resource_type=resource_type, workspace_id=workspace_id
255
+ resource_type=resource_type, project_id=project_id
256
256
  )
257
257
  filter_model.configure_rbac(
258
258
  authenticated_user_id=auth_context.user.id, id=allowed_ids
@@ -318,7 +318,7 @@ def verify_permissions_and_delete_entity(
318
318
  def verify_permissions_and_prune_entities(
319
319
  resource_type: ResourceType,
320
320
  prune_method: Callable[..., None],
321
- workspace_id: Optional[UUID] = None,
321
+ project_id: Optional[UUID] = None,
322
322
  **kwargs: Any,
323
323
  ) -> None:
324
324
  """Verify permissions and prune entities of certain type.
@@ -326,12 +326,12 @@ def verify_permissions_and_prune_entities(
326
326
  Args:
327
327
  resource_type: The resource type of the entities to prune.
328
328
  prune_method: The method to prune the entities.
329
- workspace_id: The workspace ID to prune the entities for.
329
+ project_id: The project ID to prune the entities for.
330
330
  kwargs: Keyword arguments to pass to the prune method.
331
331
  """
332
332
  verify_permission(
333
333
  resource_type=resource_type,
334
334
  action=Action.PRUNE,
335
- workspace_id=workspace_id,
335
+ project_id=project_id,
336
336
  )
337
337
  prune_method(**kwargs)
@@ -73,15 +73,15 @@ class ResourceType(StrEnum):
73
73
  TAG = "tag"
74
74
  TRIGGER = "trigger"
75
75
  TRIGGER_EXECUTION = "trigger_execution"
76
- WORKSPACE = "workspace"
76
+ PROJECT = "project"
77
77
  # Deactivated for now
78
78
  # USER = "user"
79
79
 
80
- def is_workspace_scoped(self) -> bool:
81
- """Check if a resource type is workspace scoped.
80
+ def is_project_scoped(self) -> bool:
81
+ """Check if a resource type is project scoped.
82
82
 
83
83
  Returns:
84
- Whether the resource type is workspace scoped.
84
+ Whether the resource type is project scoped.
85
85
  """
86
86
  return self not in [
87
87
  self.FLAVOR,
@@ -91,7 +91,7 @@ class ResourceType(StrEnum):
91
91
  self.STACK_COMPONENT,
92
92
  self.TAG,
93
93
  self.SERVICE_ACCOUNT,
94
- self.WORKSPACE,
94
+ self.PROJECT,
95
95
  # Deactivated for now
96
96
  # self.USER,
97
97
  ]
@@ -102,7 +102,7 @@ class Resource(BaseModel):
102
102
 
103
103
  type: str
104
104
  id: Optional[UUID] = None
105
- workspace_id: Optional[UUID] = None
105
+ project_id: Optional[UUID] = None
106
106
 
107
107
  def __str__(self) -> str:
108
108
  """Convert to a string.
@@ -110,15 +110,15 @@ class Resource(BaseModel):
110
110
  Returns:
111
111
  Resource string representation.
112
112
  """
113
- workspace_id = self.workspace_id
114
- if self.type == ResourceType.WORKSPACE and self.id:
115
- # TODO: For now, we duplicate the workspace ID in the string
116
- # representation when describing a workspace instance, because
113
+ project_id = self.project_id
114
+ if self.type == ResourceType.PROJECT and self.id:
115
+ # TODO: For now, we duplicate the project ID in the string
116
+ # representation when describing a project instance, because
117
117
  # this is what is expected by the RBAC implementation.
118
- workspace_id = self.id
118
+ project_id = self.id
119
119
 
120
- if workspace_id:
121
- representation = f"{workspace_id}:"
120
+ if project_id:
121
+ representation = f"{project_id}:"
122
122
  else:
123
123
  representation = ""
124
124
  representation += self.type
@@ -128,11 +128,11 @@ class Resource(BaseModel):
128
128
  return representation
129
129
 
130
130
  @model_validator(mode="after")
131
- def validate_workspace_id(self) -> "Resource":
132
- """Validate that workspace_id is set in combination with workspace-scoped resource types.
131
+ def validate_project_id(self) -> "Resource":
132
+ """Validate that project_id is set in combination with project-scoped resource types.
133
133
 
134
134
  Raises:
135
- ValueError: If workspace_id is not set for a workspace-scoped
135
+ ValueError: If project_id is not set for a project-scoped
136
136
  resource or set for an unscoped resource.
137
137
 
138
138
  Returns:
@@ -140,15 +140,15 @@ class Resource(BaseModel):
140
140
  """
141
141
  resource_type = ResourceType(self.type)
142
142
 
143
- if resource_type.is_workspace_scoped() and not self.workspace_id:
143
+ if resource_type.is_project_scoped() and not self.project_id:
144
144
  raise ValueError(
145
- "workspace_id must be set for workspace-scoped resource type "
145
+ "project_id must be set for project-scoped resource type "
146
146
  f"'{self.type}'"
147
147
  )
148
148
 
149
- if not resource_type.is_workspace_scoped() and self.workspace_id:
149
+ if not resource_type.is_project_scoped() and self.project_id:
150
150
  raise ValueError(
151
- "workspace_id must not be set for global resource type "
151
+ "project_id must not be set for global resource type "
152
152
  f"'{self.type}'"
153
153
  )
154
154
 
@@ -65,7 +65,7 @@ class RBACSqlZenStore(SqlZenStore):
65
65
  verify_permission(
66
66
  resource_type=ResourceType.MODEL,
67
67
  action=Action.CREATE,
68
- workspace_id=model_request.workspace,
68
+ project_id=model_request.project,
69
69
  )
70
70
  check_entitlement(resource_type=ResourceType.MODEL)
71
71
  except Exception as e:
@@ -80,7 +80,7 @@ class RBACSqlZenStore(SqlZenStore):
80
80
  try:
81
81
  model_response = self.get_model_by_name_or_id(
82
82
  model_name_or_id=model_request.name,
83
- workspace=model_request.workspace,
83
+ project=model_request.project,
84
84
  )
85
85
  created = False
86
86
  except KeyError:
@@ -152,7 +152,7 @@ class RBACSqlZenStore(SqlZenStore):
152
152
  verify_permission(
153
153
  resource_type=ResourceType.MODEL_VERSION,
154
154
  action=Action.CREATE,
155
- workspace_id=model_version_request.workspace,
155
+ project_id=model_version_request.project,
156
156
  )
157
157
  except Exception as e:
158
158
  allow_creation = False
@@ -32,10 +32,10 @@ from zenml.exceptions import IllegalOperationError
32
32
  from zenml.models import (
33
33
  BaseIdentifiedResponse,
34
34
  Page,
35
+ ProjectScopedRequest,
36
+ ProjectScopedResponse,
35
37
  UserResponse,
36
38
  UserScopedResponse,
37
- WorkspaceScopedRequest,
38
- WorkspaceScopedResponse,
39
39
  )
40
40
  from zenml.zen_server.auth import get_auth_context
41
41
  from zenml.zen_server.rbac.models import Action, Resource, ResourceType
@@ -300,7 +300,7 @@ def verify_permission(
300
300
  resource_type: str,
301
301
  action: Action,
302
302
  resource_id: Optional[UUID] = None,
303
- workspace_id: Optional[UUID] = None,
303
+ project_id: Optional[UUID] = None,
304
304
  ) -> None:
305
305
  """Verifies if a user has permission to perform an action on a resource.
306
306
 
@@ -309,11 +309,11 @@ def verify_permission(
309
309
  action on.
310
310
  action: The action the user wants to perform.
311
311
  resource_id: ID of the resource the user wants to perform the action on.
312
- workspace_id: ID of the workspace the user wants to perform the action
313
- on. Only used for workspace scoped resources.
312
+ project_id: ID of the project the user wants to perform the action
313
+ on. Only used for project scoped resources.
314
314
  """
315
315
  resource = Resource(
316
- type=resource_type, id=resource_id, workspace_id=workspace_id
316
+ type=resource_type, id=resource_id, project_id=project_id
317
317
  )
318
318
  batch_verify_permissions(resources={resource}, action=action)
319
319
 
@@ -321,15 +321,15 @@ def verify_permission(
321
321
  def get_allowed_resource_ids(
322
322
  resource_type: str,
323
323
  action: Action = Action.READ,
324
- workspace_id: Optional[UUID] = None,
324
+ project_id: Optional[UUID] = None,
325
325
  ) -> Optional[Set[UUID]]:
326
326
  """Get all resource IDs of a resource type that a user can access.
327
327
 
328
328
  Args:
329
329
  resource_type: The resource type.
330
330
  action: The action the user wants to perform on the resource.
331
- workspace_id: Optional workspace ID to filter the resources by.
332
- Required for workspace scoped resources.
331
+ project_id: Optional project ID to filter the resources by.
332
+ Required for project scoped resources.
333
333
 
334
334
  Returns:
335
335
  A list of resource IDs or `None` if the user has full access to the
@@ -346,7 +346,7 @@ def get_allowed_resource_ids(
346
346
  allowed_ids,
347
347
  ) = rbac().list_allowed_resource_ids(
348
348
  user=auth_context.user,
349
- resource=Resource(type=resource_type, workspace_id=workspace_id),
349
+ resource=Resource(type=resource_type, project_id=project_id),
350
350
  action=action,
351
351
  )
352
352
 
@@ -371,21 +371,19 @@ def get_resource_for_model(model: AnyModel) -> Optional[Resource]:
371
371
  # This model is not tied to any RBAC resource type
372
372
  return None
373
373
 
374
- workspace_id: Optional[UUID] = None
375
- if isinstance(model, WorkspaceScopedResponse):
376
- # A workspace scoped response is always scoped to a specific workspace
377
- workspace_id = model.workspace.id
378
- elif isinstance(model, WorkspaceScopedRequest):
379
- # A workspace scoped request is always scoped to a specific workspace
380
- workspace_id = model.workspace
374
+ project_id: Optional[UUID] = None
375
+ if isinstance(model, ProjectScopedResponse):
376
+ # A project scoped response is always scoped to a specific project
377
+ project_id = model.project.id
378
+ elif isinstance(model, ProjectScopedRequest):
379
+ # A project scoped request is always scoped to a specific project
380
+ project_id = model.project
381
381
 
382
382
  resource_id: Optional[UUID] = None
383
383
  if isinstance(model, BaseIdentifiedResponse):
384
384
  resource_id = model.id
385
385
 
386
- return Resource(
387
- type=resource_type, id=resource_id, workspace_id=workspace_id
388
- )
386
+ return Resource(type=resource_type, id=resource_id, project_id=project_id)
389
387
 
390
388
 
391
389
  def get_surrogate_permission_model_for_model(
@@ -456,6 +454,8 @@ def get_resource_type_for_model(
456
454
  PipelineResponse,
457
455
  PipelineRunRequest,
458
456
  PipelineRunResponse,
457
+ ProjectRequest,
458
+ ProjectResponse,
459
459
  RunMetadataRequest,
460
460
  RunTemplateRequest,
461
461
  RunTemplateResponse,
@@ -475,8 +475,6 @@ def get_resource_type_for_model(
475
475
  TriggerExecutionResponse,
476
476
  TriggerRequest,
477
477
  TriggerResponse,
478
- WorkspaceRequest,
479
- WorkspaceResponse,
480
478
  )
481
479
 
482
480
  mapping: Dict[
@@ -528,8 +526,8 @@ def get_resource_type_for_model(
528
526
  TriggerResponse: ResourceType.TRIGGER,
529
527
  TriggerExecutionRequest: ResourceType.TRIGGER_EXECUTION,
530
528
  TriggerExecutionResponse: ResourceType.TRIGGER_EXECUTION,
531
- WorkspaceResponse: ResourceType.WORKSPACE,
532
- WorkspaceRequest: ResourceType.WORKSPACE,
529
+ ProjectResponse: ResourceType.PROJECT,
530
+ ProjectRequest: ResourceType.PROJECT,
533
531
  # UserResponse: ResourceType.USER,
534
532
  }
535
533
 
@@ -673,7 +671,7 @@ def get_schema_for_resource_type(
673
671
  ResourceType.SERVICE: ServiceSchema,
674
672
  ResourceType.TAG: TagSchema,
675
673
  ResourceType.SERVICE_ACCOUNT: UserSchema,
676
- # ResourceType.WORKSPACE: WorkspaceSchema,
674
+ # ResourceType.PROJECT: ProjectSchema,
677
675
  ResourceType.PIPELINE_RUN: PipelineRunSchema,
678
676
  ResourceType.PIPELINE_DEPLOYMENT: PipelineDeploymentSchema,
679
677
  ResourceType.PIPELINE_BUILD: PipelineBuildSchema,