You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by di...@apache.org on 2026/08/11 14:06:16 UTC

(airavata) branch refactor-single-module updated: Refactoring data models and adding scp data models

This is an automated email from the ASF dual-hosted git repository.

DImuthuUpe pushed a commit to branch refactor-single-module
in repository https://gitbox.apache.org/repos/asf/airavata.git


The following commit(s) were added to refs/heads/refactor-single-module by this push:
     new 62b70035a3 Refactoring data models and adding scp data models
62b70035a3 is described below

commit 62b70035a386bd089f3c03a37078fddd2ef8c0f1
Author: DImuthuUpe <di...@gmail.com>
AuthorDate: Tue Aug 11 10:06:10 2026 -0400

    Refactoring data models and adding scp data models
---
 ...usterController.java => ClusterController.java} |  36 +++---
 .../airavata/api/ClusterCredentialController.java  |  65 ++++++++++
 .../airavata/api/ClusterPartitionController.java   |  61 +++++++++
 .../org/apache/airavata/api/SCPDataController.java |  63 ++++++++++
 .../api/SlurmClusterCredentialController.java      |  68 ----------
 .../airavata/api/SlurmPartitionController.java     |  60 ---------
 .../BatchApplicationDeploymentEntity.java          |   8 +-
 .../model/deployment/BatchJobConfigs.java          |   2 +-
 .../service/BatchApplicationDeploymentService.java |  10 +-
 ...stDto.java => ClusterCredentialRequestDto.java} |   2 +-
 ...eDto.java => ClusterCredentialResponseDto.java} |  12 +-
 ...estDto.java => ClusterPartitionRequestDto.java} |   2 +-
 ...seDto.java => ClusterPartitionResponseDto.java} |   2 +-
 ...usterRequestDto.java => ClusterRequestDto.java} |   4 +-
 ...terResponseDto.java => ClusterResponseDto.java} |   8 +-
 ...ialMapper.java => ClusterCredentialMapper.java} |  12 +-
 ...{SlurmClusterMapper.java => ClusterMapper.java} |  16 +--
 ...tionMapper.java => ClusterPartitionMapper.java} |  14 +--
 ...ialEntity.java => ClusterCredentialEntity.java} |  18 +--
 ...{SlurmClusterEntity.java => ClusterEntity.java} |   8 +-
 ...tionEntity.java => ClusterPartitionEntity.java} |   8 +-
 .../repository/ClusterCredentialRepository.java    |  16 +++
 ...sitory.java => ClusterPartitionRepository.java} |   8 +-
 ...usterRepository.java => ClusterRepository.java} |   4 +-
 .../SlurmClusterCredentialRepository.java          |  16 ---
 ...lService.java => ClusterCredentialService.java} |  58 ++++-----
 ...onService.java => ClusterPartitionService.java} |  50 ++++----
 ...lurmClusterService.java => ClusterService.java} |  32 ++---
 .../airavata/data/dto/SCPDataRequestDto.java       |  68 ++++++++++
 .../airavata/data/dto/SCPDataResponseDto.java      |  80 ++++++++++++
 .../apache/airavata/data/mapper/SCPDataMapper.java |  37 ++++++
 .../airavata/data/model/DataProvisionStatus.java   |  10 ++
 .../apache/airavata/data/model/SCPDataEntity.java  | 102 +++++++++++++++
 .../data/repository/SCPDataRepository.java         |  12 ++
 .../airavata/data/service/SCPDataService.java      | 138 +++++++++++++++++++++
 35 files changed, 809 insertions(+), 301 deletions(-)

diff --git a/src/main/java/org/apache/airavata/api/SlurmClusterController.java b/src/main/java/org/apache/airavata/api/ClusterController.java
similarity index 51%
rename from src/main/java/org/apache/airavata/api/SlurmClusterController.java
rename to src/main/java/org/apache/airavata/api/ClusterController.java
index 936050b878..6ddc31af5c 100644
--- a/src/main/java/org/apache/airavata/api/SlurmClusterController.java
+++ b/src/main/java/org/apache/airavata/api/ClusterController.java
@@ -2,9 +2,9 @@ package org.apache.airavata.api;
 
 import jakarta.validation.Valid;
 import java.util.List;
-import org.apache.airavata.compute.dto.SlurmClusterRequestDto;
-import org.apache.airavata.compute.dto.SlurmClusterResponseDto;
-import org.apache.airavata.compute.service.SlurmClusterService;
+import org.apache.airavata.compute.dto.ClusterRequestDto;
+import org.apache.airavata.compute.dto.ClusterResponseDto;
+import org.apache.airavata.compute.service.ClusterService;
 import org.springframework.http.HttpStatus;
 import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -17,41 +17,41 @@ import org.springframework.web.bind.annotation.ResponseStatus;
 import org.springframework.web.bind.annotation.RestController;
 
 @RestController
-@RequestMapping("/api/v1/slurm-clusters")
-public class SlurmClusterController {
+@RequestMapping("/api/v1/clusters")
+public class ClusterController {
 
-    private final SlurmClusterService slurmClusterService;
+    private final ClusterService clusterService;
 
-    public SlurmClusterController(SlurmClusterService slurmClusterService) {
-        this.slurmClusterService = slurmClusterService;
+    public ClusterController(ClusterService clusterService) {
+        this.clusterService = clusterService;
     }
 
     @GetMapping
-    public List<SlurmClusterResponseDto> getAllClusters() {
-        return slurmClusterService.getAllClusters();
+    public List<ClusterResponseDto> getAllClusters() {
+        return clusterService.getAllClusters();
     }
 
     @GetMapping("/{clusterId}")
-    public SlurmClusterResponseDto getCluster(@PathVariable String clusterId) {
-        return slurmClusterService.getCluster(clusterId);
+    public ClusterResponseDto getCluster(@PathVariable String clusterId) {
+        return clusterService.getCluster(clusterId);
     }
 
     @PostMapping
     @ResponseStatus(HttpStatus.CREATED)
-    public SlurmClusterResponseDto createCluster(@Valid @RequestBody SlurmClusterRequestDto request) {
-        return slurmClusterService.createCluster(request);
+    public ClusterResponseDto createCluster(@Valid @RequestBody ClusterRequestDto request) {
+        return clusterService.createCluster(request);
     }
 
     @PutMapping("/{clusterId}")
-    public SlurmClusterResponseDto updateCluster(
-            @PathVariable String clusterId, @Valid @RequestBody SlurmClusterRequestDto request) {
-        return slurmClusterService.updateCluster(clusterId, request);
+    public ClusterResponseDto updateCluster(
+            @PathVariable String clusterId, @Valid @RequestBody ClusterRequestDto request) {
+        return clusterService.updateCluster(clusterId, request);
     }
 
     /** Deleting a cluster also deletes its partitions. */
     @DeleteMapping("/{clusterId}")
     @ResponseStatus(HttpStatus.NO_CONTENT)
     public void deleteCluster(@PathVariable String clusterId) {
-        slurmClusterService.deleteCluster(clusterId);
+        clusterService.deleteCluster(clusterId);
     }
 }
diff --git a/src/main/java/org/apache/airavata/api/ClusterCredentialController.java b/src/main/java/org/apache/airavata/api/ClusterCredentialController.java
new file mode 100644
index 0000000000..bcc8c4b0db
--- /dev/null
+++ b/src/main/java/org/apache/airavata/api/ClusterCredentialController.java
@@ -0,0 +1,65 @@
+package org.apache.airavata.api;
+
+import jakarta.validation.Valid;
+import java.util.List;
+import org.apache.airavata.compute.dto.ClusterCredentialRequestDto;
+import org.apache.airavata.compute.dto.ClusterCredentialResponseDto;
+import org.apache.airavata.compute.service.ClusterCredentialService;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+
+/** The owning user is never a request parameter — see {@code ClusterCredentialService.createCredential}. */
+@RestController
+@RequestMapping("/api/v1/cluster-credentials")
+public class ClusterCredentialController {
+
+    private final ClusterCredentialService clusterCredentialService;
+
+    public ClusterCredentialController(ClusterCredentialService clusterCredentialService) {
+        this.clusterCredentialService = clusterCredentialService;
+    }
+
+    /** Every binding across every user — admin only. Optionally scoped to {@code clusterId}. */
+    @GetMapping
+    public List<ClusterCredentialResponseDto> getAllCredentials(@RequestParam(required = false) String clusterId) {
+        return clusterCredentialService.getAllCredentials(clusterId);
+    }
+
+    /** The caller's own bindings. Optionally scoped to {@code clusterId}. */
+    @GetMapping("/me")
+    public List<ClusterCredentialResponseDto> getMyCredentials(@RequestParam(required = false) String clusterId) {
+        return clusterCredentialService.getMyCredentials(clusterId);
+    }
+
+    @GetMapping("/{id}")
+    public ClusterCredentialResponseDto getCredential(@PathVariable String id) {
+        return clusterCredentialService.getCredential(id);
+    }
+
+    @PostMapping
+    @ResponseStatus(HttpStatus.CREATED)
+    public ClusterCredentialResponseDto createCredential(@Valid @RequestBody ClusterCredentialRequestDto request) {
+        return clusterCredentialService.createCredential(request);
+    }
+
+    @PutMapping("/{id}")
+    public ClusterCredentialResponseDto updateCredential(
+            @PathVariable String id, @Valid @RequestBody ClusterCredentialRequestDto request) {
+        return clusterCredentialService.updateCredential(id, request);
+    }
+
+    @DeleteMapping("/{id}")
+    @ResponseStatus(HttpStatus.NO_CONTENT)
+    public void deleteCredential(@PathVariable String id) {
+        clusterCredentialService.deleteCredential(id);
+    }
+}
diff --git a/src/main/java/org/apache/airavata/api/ClusterPartitionController.java b/src/main/java/org/apache/airavata/api/ClusterPartitionController.java
new file mode 100644
index 0000000000..c9d69d776c
--- /dev/null
+++ b/src/main/java/org/apache/airavata/api/ClusterPartitionController.java
@@ -0,0 +1,61 @@
+package org.apache.airavata.api;
+
+import jakarta.validation.Valid;
+import java.util.List;
+import org.apache.airavata.compute.dto.ClusterPartitionRequestDto;
+import org.apache.airavata.compute.dto.ClusterPartitionResponseDto;
+import org.apache.airavata.compute.service.ClusterPartitionService;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+
+/** Partitions are a sub-resource of their cluster; every path is scoped by cluster id. */
+@RestController
+@RequestMapping("/api/v1/clusters/{clusterId}/partitions")
+public class ClusterPartitionController {
+
+    private final ClusterPartitionService clusterPartitionService;
+
+    public ClusterPartitionController(ClusterPartitionService clusterPartitionService) {
+        this.clusterPartitionService = clusterPartitionService;
+    }
+
+    @GetMapping
+    public List<ClusterPartitionResponseDto> getPartitions(@PathVariable String clusterId) {
+        return clusterPartitionService.getPartitions(clusterId);
+    }
+
+    @GetMapping("/{partitionId}")
+    public ClusterPartitionResponseDto getPartition(
+            @PathVariable String clusterId, @PathVariable String partitionId) {
+        return clusterPartitionService.getPartition(clusterId, partitionId);
+    }
+
+    @PostMapping
+    @ResponseStatus(HttpStatus.CREATED)
+    public ClusterPartitionResponseDto createPartition(
+            @PathVariable String clusterId, @Valid @RequestBody ClusterPartitionRequestDto request) {
+        return clusterPartitionService.createPartition(clusterId, request);
+    }
+
+    @PutMapping("/{partitionId}")
+    public ClusterPartitionResponseDto updatePartition(
+            @PathVariable String clusterId,
+            @PathVariable String partitionId,
+            @Valid @RequestBody ClusterPartitionRequestDto request) {
+        return clusterPartitionService.updatePartition(clusterId, partitionId, request);
+    }
+
+    @DeleteMapping("/{partitionId}")
+    @ResponseStatus(HttpStatus.NO_CONTENT)
+    public void deletePartition(@PathVariable String clusterId, @PathVariable String partitionId) {
+        clusterPartitionService.deletePartition(clusterId, partitionId);
+    }
+}
diff --git a/src/main/java/org/apache/airavata/api/SCPDataController.java b/src/main/java/org/apache/airavata/api/SCPDataController.java
new file mode 100644
index 0000000000..7effd6eb94
--- /dev/null
+++ b/src/main/java/org/apache/airavata/api/SCPDataController.java
@@ -0,0 +1,63 @@
+package org.apache.airavata.api;
+
+import jakarta.validation.Valid;
+import java.util.List;
+import org.apache.airavata.data.dto.SCPDataRequestDto;
+import org.apache.airavata.data.dto.SCPDataResponseDto;
+import org.apache.airavata.data.service.SCPDataService;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+
+/** The owning user is never a request parameter — see {@code SCPDataService.createData}. */
+@RestController
+@RequestMapping("/api/v1/scp-data")
+public class SCPDataController {
+
+    private final SCPDataService scpDataService;
+
+    public SCPDataController(SCPDataService scpDataService) {
+        this.scpDataService = scpDataService;
+    }
+
+    /** Every data registration across every user — admin only. */
+    @GetMapping
+    public List<SCPDataResponseDto> getAllData() {
+        return scpDataService.getAllData();
+    }
+
+    /** The caller's own data registrations. */
+    @GetMapping("/me")
+    public List<SCPDataResponseDto> getMyData() {
+        return scpDataService.getMyData();
+    }
+
+    @GetMapping("/{id}")
+    public SCPDataResponseDto getData(@PathVariable String id) {
+        return scpDataService.getData(id);
+    }
+
+    @PostMapping
+    @ResponseStatus(HttpStatus.CREATED)
+    public SCPDataResponseDto createData(@Valid @RequestBody SCPDataRequestDto request) {
+        return scpDataService.createData(request);
+    }
+
+    @PutMapping("/{id}")
+    public SCPDataResponseDto updateData(@PathVariable String id, @Valid @RequestBody SCPDataRequestDto request) {
+        return scpDataService.updateData(id, request);
+    }
+
+    @DeleteMapping("/{id}")
+    @ResponseStatus(HttpStatus.NO_CONTENT)
+    public void deleteData(@PathVariable String id) {
+        scpDataService.deleteData(id);
+    }
+}
diff --git a/src/main/java/org/apache/airavata/api/SlurmClusterCredentialController.java b/src/main/java/org/apache/airavata/api/SlurmClusterCredentialController.java
deleted file mode 100644
index 63923c1a0c..0000000000
--- a/src/main/java/org/apache/airavata/api/SlurmClusterCredentialController.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package org.apache.airavata.api;
-
-import jakarta.validation.Valid;
-import java.util.List;
-import org.apache.airavata.compute.dto.SlurmClusterCredentialRequestDto;
-import org.apache.airavata.compute.dto.SlurmClusterCredentialResponseDto;
-import org.apache.airavata.compute.service.SlurmClusterCredentialService;
-import org.springframework.http.HttpStatus;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.ResponseStatus;
-import org.springframework.web.bind.annotation.RestController;
-
-/** The owning user is never a request parameter — see {@code SlurmClusterCredentialService.createCredential}. */
-@RestController
-@RequestMapping("/api/v1/slurm-cluster-credentials")
-public class SlurmClusterCredentialController {
-
-    private final SlurmClusterCredentialService slurmClusterCredentialService;
-
-    public SlurmClusterCredentialController(SlurmClusterCredentialService slurmClusterCredentialService) {
-        this.slurmClusterCredentialService = slurmClusterCredentialService;
-    }
-
-    /** Every binding across every user — admin only. Optionally scoped to {@code clusterId}. */
-    @GetMapping
-    public List<SlurmClusterCredentialResponseDto> getAllCredentials(
-            @RequestParam(required = false) String clusterId) {
-        return slurmClusterCredentialService.getAllCredentials(clusterId);
-    }
-
-    /** The caller's own bindings. Optionally scoped to {@code clusterId}. */
-    @GetMapping("/me")
-    public List<SlurmClusterCredentialResponseDto> getMyCredentials(
-            @RequestParam(required = false) String clusterId) {
-        return slurmClusterCredentialService.getMyCredentials(clusterId);
-    }
-
-    @GetMapping("/{id}")
-    public SlurmClusterCredentialResponseDto getCredential(@PathVariable String id) {
-        return slurmClusterCredentialService.getCredential(id);
-    }
-
-    @PostMapping
-    @ResponseStatus(HttpStatus.CREATED)
-    public SlurmClusterCredentialResponseDto createCredential(
-            @Valid @RequestBody SlurmClusterCredentialRequestDto request) {
-        return slurmClusterCredentialService.createCredential(request);
-    }
-
-    @PutMapping("/{id}")
-    public SlurmClusterCredentialResponseDto updateCredential(
-            @PathVariable String id, @Valid @RequestBody SlurmClusterCredentialRequestDto request) {
-        return slurmClusterCredentialService.updateCredential(id, request);
-    }
-
-    @DeleteMapping("/{id}")
-    @ResponseStatus(HttpStatus.NO_CONTENT)
-    public void deleteCredential(@PathVariable String id) {
-        slurmClusterCredentialService.deleteCredential(id);
-    }
-}
diff --git a/src/main/java/org/apache/airavata/api/SlurmPartitionController.java b/src/main/java/org/apache/airavata/api/SlurmPartitionController.java
deleted file mode 100644
index 87e27a5471..0000000000
--- a/src/main/java/org/apache/airavata/api/SlurmPartitionController.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package org.apache.airavata.api;
-
-import jakarta.validation.Valid;
-import java.util.List;
-import org.apache.airavata.compute.dto.SlurmPartitionRequestDto;
-import org.apache.airavata.compute.dto.SlurmPartitionResponseDto;
-import org.apache.airavata.compute.service.SlurmPartitionService;
-import org.springframework.http.HttpStatus;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.ResponseStatus;
-import org.springframework.web.bind.annotation.RestController;
-
-/** Partitions are a sub-resource of their cluster; every path is scoped by cluster id. */
-@RestController
-@RequestMapping("/api/v1/slurm-clusters/{clusterId}/partitions")
-public class SlurmPartitionController {
-
-    private final SlurmPartitionService slurmPartitionService;
-
-    public SlurmPartitionController(SlurmPartitionService slurmPartitionService) {
-        this.slurmPartitionService = slurmPartitionService;
-    }
-
-    @GetMapping
-    public List<SlurmPartitionResponseDto> getPartitions(@PathVariable String clusterId) {
-        return slurmPartitionService.getPartitions(clusterId);
-    }
-
-    @GetMapping("/{partitionId}")
-    public SlurmPartitionResponseDto getPartition(@PathVariable String clusterId, @PathVariable String partitionId) {
-        return slurmPartitionService.getPartition(clusterId, partitionId);
-    }
-
-    @PostMapping
-    @ResponseStatus(HttpStatus.CREATED)
-    public SlurmPartitionResponseDto createPartition(
-            @PathVariable String clusterId, @Valid @RequestBody SlurmPartitionRequestDto request) {
-        return slurmPartitionService.createPartition(clusterId, request);
-    }
-
-    @PutMapping("/{partitionId}")
-    public SlurmPartitionResponseDto updatePartition(
-            @PathVariable String clusterId,
-            @PathVariable String partitionId,
-            @Valid @RequestBody SlurmPartitionRequestDto request) {
-        return slurmPartitionService.updatePartition(clusterId, partitionId, request);
-    }
-
-    @DeleteMapping("/{partitionId}")
-    @ResponseStatus(HttpStatus.NO_CONTENT)
-    public void deletePartition(@PathVariable String clusterId, @PathVariable String partitionId) {
-        slurmPartitionService.deletePartition(clusterId, partitionId);
-    }
-}
diff --git a/src/main/java/org/apache/airavata/application/model/deployment/BatchApplicationDeploymentEntity.java b/src/main/java/org/apache/airavata/application/model/deployment/BatchApplicationDeploymentEntity.java
index 7060283806..6ffa6d80d9 100644
--- a/src/main/java/org/apache/airavata/application/model/deployment/BatchApplicationDeploymentEntity.java
+++ b/src/main/java/org/apache/airavata/application/model/deployment/BatchApplicationDeploymentEntity.java
@@ -1,7 +1,7 @@
 package org.apache.airavata.application.model.deployment;
 
 import org.apache.airavata.application.model.template.ApplicationTemplateEntity;
-import org.apache.airavata.compute.model.SlurmClusterEntity;
+import org.apache.airavata.compute.model.ClusterEntity;
 import org.apache.airavata.credentials.model.SSHUserCredential;
 
 import jakarta.persistence.CascadeType;
@@ -25,7 +25,7 @@ public class BatchApplicationDeploymentEntity {
 
     @ManyToOne
     @JoinColumn(name = "cluster_id", foreignKey = @ForeignKey(name = "fk_dep_slurm_cluster"))
-    private SlurmClusterEntity slurmCluster;
+    private ClusterEntity slurmCluster;
 
     @ManyToOne
     @JoinColumn(name = "template_id", foreignKey = @ForeignKey(name = "fk_dep_app_template"))
@@ -70,11 +70,11 @@ public class BatchApplicationDeploymentEntity {
         this.deploymentId = deploymentId;
     }
 
-    public SlurmClusterEntity getSlurmCluster() {
+    public ClusterEntity getSlurmCluster() {
         return slurmCluster;
     }
 
-    public void setSlurmCluster(SlurmClusterEntity slurmCluster) {
+    public void setSlurmCluster(ClusterEntity slurmCluster) {
         this.slurmCluster = slurmCluster;
     }
 
diff --git a/src/main/java/org/apache/airavata/application/model/deployment/BatchJobConfigs.java b/src/main/java/org/apache/airavata/application/model/deployment/BatchJobConfigs.java
index a20bc9449f..f7824d3f9e 100644
--- a/src/main/java/org/apache/airavata/application/model/deployment/BatchJobConfigs.java
+++ b/src/main/java/org/apache/airavata/application/model/deployment/BatchJobConfigs.java
@@ -9,7 +9,7 @@ import jakarta.persistence.Id;
 /**
  * Batch-scheduler resource request for a {@link BatchApplicationDeploymentEntity}. Owned
  * by its deployment — created, replaced and deleted with it — rather than a shareable
- * aggregate like {@code ApplicationTemplateEntity} or {@code SlurmClusterEntity}.
+ * aggregate like {@code ApplicationTemplateEntity} or {@code ClusterEntity}.
  */
 @Entity
 public class BatchJobConfigs {
diff --git a/src/main/java/org/apache/airavata/application/service/BatchApplicationDeploymentService.java b/src/main/java/org/apache/airavata/application/service/BatchApplicationDeploymentService.java
index 0767d46820..e43b647aca 100644
--- a/src/main/java/org/apache/airavata/application/service/BatchApplicationDeploymentService.java
+++ b/src/main/java/org/apache/airavata/application/service/BatchApplicationDeploymentService.java
@@ -8,8 +8,8 @@ import org.apache.airavata.application.model.deployment.BatchApplicationDeployme
 import org.apache.airavata.application.model.template.ApplicationTemplateEntity;
 import org.apache.airavata.application.repository.ApplicationTemplateRepository;
 import org.apache.airavata.application.repository.BatchApplicationDeploymentRepository;
-import org.apache.airavata.compute.model.SlurmClusterEntity;
-import org.apache.airavata.compute.repository.SlurmClusterRepository;
+import org.apache.airavata.compute.model.ClusterEntity;
+import org.apache.airavata.compute.repository.ClusterRepository;
 import org.apache.airavata.credentials.model.SSHUserCredential;
 import org.apache.airavata.credentials.repository.SSHUserCredentialRepository;
 import org.springframework.http.HttpStatus;
@@ -24,14 +24,14 @@ public class BatchApplicationDeploymentService {
 
     private final BatchApplicationDeploymentRepository deploymentRepository;
     private final ApplicationTemplateRepository templateRepository;
-    private final SlurmClusterRepository clusterRepository;
+    private final ClusterRepository clusterRepository;
     private final SSHUserCredentialRepository credentialRepository;
     private final BatchApplicationDeploymentMapper mapper;
 
     public BatchApplicationDeploymentService(
             BatchApplicationDeploymentRepository deploymentRepository,
             ApplicationTemplateRepository templateRepository,
-            SlurmClusterRepository clusterRepository,
+            ClusterRepository clusterRepository,
             SSHUserCredentialRepository credentialRepository,
             BatchApplicationDeploymentMapper mapper) {
         this.deploymentRepository = deploymentRepository;
@@ -104,7 +104,7 @@ public class BatchApplicationDeploymentService {
      * The cluster reference is optional — the column is nullable, so an absent id leaves
      * the deployment unattached rather than failing. A supplied id must resolve.
      */
-    private SlurmClusterEntity resolveCluster(String clusterId) {
+    private ClusterEntity resolveCluster(String clusterId) {
         if (clusterId == null || clusterId.isBlank()) {
             return null;
         }
diff --git a/src/main/java/org/apache/airavata/compute/dto/SlurmClusterCredentialRequestDto.java b/src/main/java/org/apache/airavata/compute/dto/ClusterCredentialRequestDto.java
similarity index 95%
rename from src/main/java/org/apache/airavata/compute/dto/SlurmClusterCredentialRequestDto.java
rename to src/main/java/org/apache/airavata/compute/dto/ClusterCredentialRequestDto.java
index 72f64542fd..989c21c1ca 100644
--- a/src/main/java/org/apache/airavata/compute/dto/SlurmClusterCredentialRequestDto.java
+++ b/src/main/java/org/apache/airavata/compute/dto/ClusterCredentialRequestDto.java
@@ -9,7 +9,7 @@ import jakarta.validation.constraints.NotBlank;
  * token, never from client input, so a caller cannot bind a credential on another user's
  * behalf.
  */
-public class SlurmClusterCredentialRequestDto {
+public class ClusterCredentialRequestDto {
 
     @NotBlank(message = "Cluster id cannot be blank")
     private String clusterId;
diff --git a/src/main/java/org/apache/airavata/compute/dto/SlurmClusterCredentialResponseDto.java b/src/main/java/org/apache/airavata/compute/dto/ClusterCredentialResponseDto.java
similarity index 68%
rename from src/main/java/org/apache/airavata/compute/dto/SlurmClusterCredentialResponseDto.java
rename to src/main/java/org/apache/airavata/compute/dto/ClusterCredentialResponseDto.java
index 726936549f..d76eae3b30 100644
--- a/src/main/java/org/apache/airavata/compute/dto/SlurmClusterCredentialResponseDto.java
+++ b/src/main/java/org/apache/airavata/compute/dto/ClusterCredentialResponseDto.java
@@ -1,19 +1,19 @@
 package org.apache.airavata.compute.dto;
 
 /** Read view of a per-user SSH credential binding on a Slurm cluster. */
-public class SlurmClusterCredentialResponseDto {
+public class ClusterCredentialResponseDto {
 
-    private String slurmClusterCredentialId;
+    private String clusterCredentialId;
     private String clusterId;
     private String sshCredentialId;
     private String userId;
 
-    public String getSlurmClusterCredentialId() {
-        return slurmClusterCredentialId;
+    public String getClusterCredentialId() {
+        return clusterCredentialId;
     }
 
-    public void setSlurmClusterCredentialId(String slurmClusterCredentialId) {
-        this.slurmClusterCredentialId = slurmClusterCredentialId;
+    public void setClusterCredentialId(String clusterCredentialId) {
+        this.clusterCredentialId = clusterCredentialId;
     }
 
     public String getClusterId() {
diff --git a/src/main/java/org/apache/airavata/compute/dto/SlurmPartitionRequestDto.java b/src/main/java/org/apache/airavata/compute/dto/ClusterPartitionRequestDto.java
similarity index 98%
rename from src/main/java/org/apache/airavata/compute/dto/SlurmPartitionRequestDto.java
rename to src/main/java/org/apache/airavata/compute/dto/ClusterPartitionRequestDto.java
index bf304b5a15..cc131d25fa 100644
--- a/src/main/java/org/apache/airavata/compute/dto/SlurmPartitionRequestDto.java
+++ b/src/main/java/org/apache/airavata/compute/dto/ClusterPartitionRequestDto.java
@@ -3,7 +3,7 @@ package org.apache.airavata.compute.dto;
 import jakarta.validation.constraints.NotBlank;
 
 /** Create/update payload for a partition of a Slurm cluster. */
-public class SlurmPartitionRequestDto {
+public class ClusterPartitionRequestDto {
 
     @NotBlank(message = "Partition name cannot be blank")
     private String name;
diff --git a/src/main/java/org/apache/airavata/compute/dto/SlurmPartitionResponseDto.java b/src/main/java/org/apache/airavata/compute/dto/ClusterPartitionResponseDto.java
similarity index 98%
rename from src/main/java/org/apache/airavata/compute/dto/SlurmPartitionResponseDto.java
rename to src/main/java/org/apache/airavata/compute/dto/ClusterPartitionResponseDto.java
index eeb81197b8..93f9ef5418 100644
--- a/src/main/java/org/apache/airavata/compute/dto/SlurmPartitionResponseDto.java
+++ b/src/main/java/org/apache/airavata/compute/dto/ClusterPartitionResponseDto.java
@@ -1,7 +1,7 @@
 package org.apache.airavata.compute.dto;
 
 /** Read view of a partition; the owning cluster is referenced by id only. */
-public class SlurmPartitionResponseDto {
+public class ClusterPartitionResponseDto {
 
     private String partitionId;
     private String clusterId;
diff --git a/src/main/java/org/apache/airavata/compute/dto/SlurmClusterRequestDto.java b/src/main/java/org/apache/airavata/compute/dto/ClusterRequestDto.java
similarity index 90%
rename from src/main/java/org/apache/airavata/compute/dto/SlurmClusterRequestDto.java
rename to src/main/java/org/apache/airavata/compute/dto/ClusterRequestDto.java
index 55bb969de4..8db49b7d50 100644
--- a/src/main/java/org/apache/airavata/compute/dto/SlurmClusterRequestDto.java
+++ b/src/main/java/org/apache/airavata/compute/dto/ClusterRequestDto.java
@@ -4,10 +4,10 @@ import jakarta.validation.constraints.NotBlank;
 
 /**
  * Create/update payload for a Slurm cluster. Partitions are not accepted here — they are
- * managed through {@code /api/v1/slurm-clusters/{clusterId}/partitions} so that updating
+ * managed through {@code /api/v1/clusters/{clusterId}/partitions} so that updating
  * a cluster cannot silently drop them.
  */
-public class SlurmClusterRequestDto {
+public class ClusterRequestDto {
 
     @NotBlank(message = "Cluster name cannot be blank")
     private String clusterName;
diff --git a/src/main/java/org/apache/airavata/compute/dto/SlurmClusterResponseDto.java b/src/main/java/org/apache/airavata/compute/dto/ClusterResponseDto.java
similarity index 84%
rename from src/main/java/org/apache/airavata/compute/dto/SlurmClusterResponseDto.java
rename to src/main/java/org/apache/airavata/compute/dto/ClusterResponseDto.java
index 3a1834ea8e..6a27f7d3cb 100644
--- a/src/main/java/org/apache/airavata/compute/dto/SlurmClusterResponseDto.java
+++ b/src/main/java/org/apache/airavata/compute/dto/ClusterResponseDto.java
@@ -3,14 +3,14 @@ package org.apache.airavata.compute.dto;
 import java.util.List;
 
 /** Read view of a Slurm cluster, including its partitions. */
-public class SlurmClusterResponseDto {
+public class ClusterResponseDto {
 
     private String clusterId;
     private String clusterName;
     private String clusterDescription;
     private String hostName;
     private String slurmHome;
-    private List<SlurmPartitionResponseDto> partitions;
+    private List<ClusterPartitionResponseDto> partitions;
 
     public String getClusterId() {
         return clusterId;
@@ -52,11 +52,11 @@ public class SlurmClusterResponseDto {
         this.slurmHome = slurmHome;
     }
 
-    public List<SlurmPartitionResponseDto> getPartitions() {
+    public List<ClusterPartitionResponseDto> getPartitions() {
         return partitions;
     }
 
-    public void setPartitions(List<SlurmPartitionResponseDto> partitions) {
+    public void setPartitions(List<ClusterPartitionResponseDto> partitions) {
         this.partitions = partitions;
     }
 }
diff --git a/src/main/java/org/apache/airavata/compute/mapper/SlurmClusterCredentialMapper.java b/src/main/java/org/apache/airavata/compute/mapper/ClusterCredentialMapper.java
similarity index 61%
rename from src/main/java/org/apache/airavata/compute/mapper/SlurmClusterCredentialMapper.java
rename to src/main/java/org/apache/airavata/compute/mapper/ClusterCredentialMapper.java
index 8aa913f4e6..df9d1565a3 100644
--- a/src/main/java/org/apache/airavata/compute/mapper/SlurmClusterCredentialMapper.java
+++ b/src/main/java/org/apache/airavata/compute/mapper/ClusterCredentialMapper.java
@@ -1,7 +1,7 @@
 package org.apache.airavata.compute.mapper;
 
-import org.apache.airavata.compute.dto.SlurmClusterCredentialResponseDto;
-import org.apache.airavata.compute.model.SlurmClusterCredentialEntity;
+import org.apache.airavata.compute.dto.ClusterCredentialResponseDto;
+import org.apache.airavata.compute.model.ClusterCredentialEntity;
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
 import org.mapstruct.ReportingPolicy;
@@ -10,16 +10,16 @@ import org.mapstruct.ReportingPolicy;
  * Entity/DTO conversion for Slurm cluster credential bindings.
  *
  * <p>There is no {@code toEntity}/{@code updateEntity} here: every field on
- * {@link SlurmClusterCredentialEntity} is an association (cluster, credential, user) and
- * every one of them is resolved by {@code SlurmClusterCredentialService} — from the
+ * {@link ClusterCredentialEntity} is an association (cluster, credential, user) and
+ * every one of them is resolved by {@code ClusterCredentialService} — from the
  * request DTO's ids, or from the caller's access token — so there is nothing left for a
  * mapper to write onto the entity.
  */
 @Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
-public interface SlurmClusterCredentialMapper {
+public interface ClusterCredentialMapper {
 
     @Mapping(target = "clusterId", source = "slurmCluster.clusterId")
     @Mapping(target = "sshCredentialId", source = "sshUserCredential.sshCredentialId")
     @Mapping(target = "userId", source = "user.userId")
-    SlurmClusterCredentialResponseDto toResponseDto(SlurmClusterCredentialEntity entity);
+    ClusterCredentialResponseDto toResponseDto(ClusterCredentialEntity entity);
 }
diff --git a/src/main/java/org/apache/airavata/compute/mapper/SlurmClusterMapper.java b/src/main/java/org/apache/airavata/compute/mapper/ClusterMapper.java
similarity index 57%
rename from src/main/java/org/apache/airavata/compute/mapper/SlurmClusterMapper.java
rename to src/main/java/org/apache/airavata/compute/mapper/ClusterMapper.java
index 15d2d441e9..149f2dac8e 100644
--- a/src/main/java/org/apache/airavata/compute/mapper/SlurmClusterMapper.java
+++ b/src/main/java/org/apache/airavata/compute/mapper/ClusterMapper.java
@@ -1,8 +1,8 @@
 package org.apache.airavata.compute.mapper;
 
-import org.apache.airavata.compute.dto.SlurmClusterRequestDto;
-import org.apache.airavata.compute.dto.SlurmClusterResponseDto;
-import org.apache.airavata.compute.model.SlurmClusterEntity;
+import org.apache.airavata.compute.dto.ClusterRequestDto;
+import org.apache.airavata.compute.dto.ClusterResponseDto;
+import org.apache.airavata.compute.model.ClusterEntity;
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
 import org.mapstruct.MappingTarget;
@@ -14,17 +14,17 @@ import org.mapstruct.ReportingPolicy;
  */
 @Mapper(
         componentModel = "spring",
-        uses = SlurmPartitionMapper.class,
+        uses = ClusterPartitionMapper.class,
         unmappedTargetPolicy = ReportingPolicy.IGNORE)
-public interface SlurmClusterMapper {
+public interface ClusterMapper {
 
-    SlurmClusterResponseDto toResponseDto(SlurmClusterEntity entity);
+    ClusterResponseDto toResponseDto(ClusterEntity entity);
 
     @Mapping(target = "clusterId", ignore = true)
     @Mapping(target = "partitions", ignore = true)
-    SlurmClusterEntity toEntity(SlurmClusterRequestDto dto);
+    ClusterEntity toEntity(ClusterRequestDto dto);
 
     @Mapping(target = "clusterId", ignore = true)
     @Mapping(target = "partitions", ignore = true)
-    void updateEntity(SlurmClusterRequestDto dto, @MappingTarget SlurmClusterEntity entity);
+    void updateEntity(ClusterRequestDto dto, @MappingTarget ClusterEntity entity);
 }
diff --git a/src/main/java/org/apache/airavata/compute/mapper/SlurmPartitionMapper.java b/src/main/java/org/apache/airavata/compute/mapper/ClusterPartitionMapper.java
similarity index 59%
rename from src/main/java/org/apache/airavata/compute/mapper/SlurmPartitionMapper.java
rename to src/main/java/org/apache/airavata/compute/mapper/ClusterPartitionMapper.java
index 97f4968f1e..8ef5458db0 100644
--- a/src/main/java/org/apache/airavata/compute/mapper/SlurmPartitionMapper.java
+++ b/src/main/java/org/apache/airavata/compute/mapper/ClusterPartitionMapper.java
@@ -1,8 +1,8 @@
 package org.apache.airavata.compute.mapper;
 
-import org.apache.airavata.compute.dto.SlurmPartitionRequestDto;
-import org.apache.airavata.compute.dto.SlurmPartitionResponseDto;
-import org.apache.airavata.compute.model.SlurmPartitionEntity;
+import org.apache.airavata.compute.dto.ClusterPartitionRequestDto;
+import org.apache.airavata.compute.dto.ClusterPartitionResponseDto;
+import org.apache.airavata.compute.model.ClusterPartitionEntity;
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
 import org.mapstruct.MappingTarget;
@@ -13,16 +13,16 @@ import org.mapstruct.ReportingPolicy;
  * service from the path, so it is never mapped off the request body.
  */
 @Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
-public interface SlurmPartitionMapper {
+public interface ClusterPartitionMapper {
 
     @Mapping(target = "clusterId", source = "slurmCluster.clusterId")
-    SlurmPartitionResponseDto toResponseDto(SlurmPartitionEntity entity);
+    ClusterPartitionResponseDto toResponseDto(ClusterPartitionEntity entity);
 
     @Mapping(target = "partitionId", ignore = true)
     @Mapping(target = "slurmCluster", ignore = true)
-    SlurmPartitionEntity toEntity(SlurmPartitionRequestDto dto);
+    ClusterPartitionEntity toEntity(ClusterPartitionRequestDto dto);
 
     @Mapping(target = "partitionId", ignore = true)
     @Mapping(target = "slurmCluster", ignore = true)
-    void updateEntity(SlurmPartitionRequestDto dto, @MappingTarget SlurmPartitionEntity entity);
+    void updateEntity(ClusterPartitionRequestDto dto, @MappingTarget ClusterPartitionEntity entity);
 }
diff --git a/src/main/java/org/apache/airavata/compute/model/SlurmClusterCredentialEntity.java b/src/main/java/org/apache/airavata/compute/model/ClusterCredentialEntity.java
similarity index 74%
rename from src/main/java/org/apache/airavata/compute/model/SlurmClusterCredentialEntity.java
rename to src/main/java/org/apache/airavata/compute/model/ClusterCredentialEntity.java
index c954636d77..3cc9b61001 100644
--- a/src/main/java/org/apache/airavata/compute/model/SlurmClusterCredentialEntity.java
+++ b/src/main/java/org/apache/airavata/compute/model/ClusterCredentialEntity.java
@@ -12,15 +12,15 @@ import jakarta.persistence.JoinColumn;
 import jakarta.persistence.ManyToOne;
 
 @Entity
-public class SlurmClusterCredentialEntity {
+public class ClusterCredentialEntity {
 
     @Id
     @GeneratedValue(strategy = GenerationType.UUID)
-    private String slurmClusterCredentialId;
+    private String clusterCredentialId;
 
     @ManyToOne
     @JoinColumn(name = "cluster_id", foreignKey = @ForeignKey(name = "fk_cluster_credential_cluster"))
-    private SlurmClusterEntity slurmCluster;
+    private ClusterEntity slurmCluster;
 
     @ManyToOne
     @JoinColumn(name = "ssh_credential_id", foreignKey = @ForeignKey(name = "fk_cluster_credential_ssh_credential"))
@@ -30,19 +30,19 @@ public class SlurmClusterCredentialEntity {
     @JoinColumn(name = "user_id", foreignKey = @ForeignKey(name = "fk_cluster_credential_user"))
     private UserEntity user;
 
-    public String getSlurmClusterCredentialId() {
-        return slurmClusterCredentialId;
+    public String getClusterCredentialId() {
+        return clusterCredentialId;
     }
 
-    public void setSlurmClusterCredentialId(String slurmClusterCredentialId) {
-        this.slurmClusterCredentialId = slurmClusterCredentialId;
+    public void setClusterCredentialId(String clusterCredentialId) {
+        this.clusterCredentialId = clusterCredentialId;
     }
 
-    public SlurmClusterEntity getSlurmCluster() {
+    public ClusterEntity getSlurmCluster() {
         return slurmCluster;
     }
 
-    public void setSlurmCluster(SlurmClusterEntity slurmCluster) {
+    public void setSlurmCluster(ClusterEntity slurmCluster) {
         this.slurmCluster = slurmCluster;
     }
 
diff --git a/src/main/java/org/apache/airavata/compute/model/SlurmClusterEntity.java b/src/main/java/org/apache/airavata/compute/model/ClusterEntity.java
similarity index 88%
rename from src/main/java/org/apache/airavata/compute/model/SlurmClusterEntity.java
rename to src/main/java/org/apache/airavata/compute/model/ClusterEntity.java
index 5bd33ea688..9f0d49b55a 100644
--- a/src/main/java/org/apache/airavata/compute/model/SlurmClusterEntity.java
+++ b/src/main/java/org/apache/airavata/compute/model/ClusterEntity.java
@@ -11,7 +11,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 @Entity
-public class SlurmClusterEntity {
+public class ClusterEntity {
 
     @Id
     @GeneratedValue(strategy = GenerationType.UUID)
@@ -29,7 +29,7 @@ public class SlurmClusterEntity {
     // Partitions are owned by the cluster: they are created, replaced and deleted
     // with it, and have no meaning outside of it.
     @OneToMany(mappedBy = "slurmCluster", cascade = CascadeType.ALL, orphanRemoval = true)
-    private List<SlurmPartitionEntity> partitions = new ArrayList<>();
+    private List<ClusterPartitionEntity> partitions = new ArrayList<>();
 
     public String getClusterId() {
         return clusterId;
@@ -71,11 +71,11 @@ public class SlurmClusterEntity {
         this.slurmHome = slurmHome;
     }
 
-    public List<SlurmPartitionEntity> getPartitions() {
+    public List<ClusterPartitionEntity> getPartitions() {
         return partitions;
     }
 
-    public void setPartitions(List<SlurmPartitionEntity> partitions) {
+    public void setPartitions(List<ClusterPartitionEntity> partitions) {
         this.partitions = partitions;
     }
 }
diff --git a/src/main/java/org/apache/airavata/compute/model/SlurmPartitionEntity.java b/src/main/java/org/apache/airavata/compute/model/ClusterPartitionEntity.java
similarity index 95%
rename from src/main/java/org/apache/airavata/compute/model/SlurmPartitionEntity.java
rename to src/main/java/org/apache/airavata/compute/model/ClusterPartitionEntity.java
index 3987f03ba1..f86893e42a 100644
--- a/src/main/java/org/apache/airavata/compute/model/SlurmPartitionEntity.java
+++ b/src/main/java/org/apache/airavata/compute/model/ClusterPartitionEntity.java
@@ -10,7 +10,7 @@ import jakarta.persistence.JoinColumn;
 import jakarta.persistence.ManyToOne;
 
 @Entity
-public class SlurmPartitionEntity {
+public class ClusterPartitionEntity {
 
     @Id
     @GeneratedValue(strategy = GenerationType.UUID)
@@ -18,7 +18,7 @@ public class SlurmPartitionEntity {
 
     @ManyToOne
     @JoinColumn(name = "cluster_id", foreignKey = @ForeignKey(name = "fk_partition_cluster"))
-    private SlurmClusterEntity slurmCluster;
+    private ClusterEntity slurmCluster;
 
     @Column(nullable = false)
     private String name;
@@ -74,11 +74,11 @@ public class SlurmPartitionEntity {
         this.partitionId = partitionId;
     }
 
-    public SlurmClusterEntity getSlurmCluster() {
+    public ClusterEntity getSlurmCluster() {
         return slurmCluster;
     }
 
-    public void setSlurmCluster(SlurmClusterEntity slurmCluster) {
+    public void setSlurmCluster(ClusterEntity slurmCluster) {
         this.slurmCluster = slurmCluster;
     }
 
diff --git a/src/main/java/org/apache/airavata/compute/repository/ClusterCredentialRepository.java b/src/main/java/org/apache/airavata/compute/repository/ClusterCredentialRepository.java
new file mode 100644
index 0000000000..141c841814
--- /dev/null
+++ b/src/main/java/org/apache/airavata/compute/repository/ClusterCredentialRepository.java
@@ -0,0 +1,16 @@
+package org.apache.airavata.compute.repository;
+
+import java.util.List;
+import org.apache.airavata.compute.model.ClusterCredentialEntity;
+import org.springframework.data.repository.ListCrudRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ClusterCredentialRepository extends ListCrudRepository<ClusterCredentialEntity, String> {
+
+    List<ClusterCredentialEntity> findBySlurmCluster_ClusterId(String clusterId);
+
+    List<ClusterCredentialEntity> findByUser_UserId(String userId);
+
+    List<ClusterCredentialEntity> findByUser_UserIdAndSlurmCluster_ClusterId(String userId, String clusterId);
+}
diff --git a/src/main/java/org/apache/airavata/compute/repository/SlurmPartitionRepository.java b/src/main/java/org/apache/airavata/compute/repository/ClusterPartitionRepository.java
similarity index 52%
rename from src/main/java/org/apache/airavata/compute/repository/SlurmPartitionRepository.java
rename to src/main/java/org/apache/airavata/compute/repository/ClusterPartitionRepository.java
index 4d6d771075..dbdb4e9dd8 100644
--- a/src/main/java/org/apache/airavata/compute/repository/SlurmPartitionRepository.java
+++ b/src/main/java/org/apache/airavata/compute/repository/ClusterPartitionRepository.java
@@ -2,18 +2,18 @@ package org.apache.airavata.compute.repository;
 
 import java.util.List;
 import java.util.Optional;
-import org.apache.airavata.compute.model.SlurmPartitionEntity;
+import org.apache.airavata.compute.model.ClusterPartitionEntity;
 import org.springframework.data.repository.ListCrudRepository;
 import org.springframework.stereotype.Repository;
 
 @Repository
-public interface SlurmPartitionRepository extends ListCrudRepository<SlurmPartitionEntity, String> {
+public interface ClusterPartitionRepository extends ListCrudRepository<ClusterPartitionEntity, String> {
 
-    List<SlurmPartitionEntity> findBySlurmCluster_ClusterId(String clusterId);
+    List<ClusterPartitionEntity> findBySlurmCluster_ClusterId(String clusterId);
 
     /**
      * Scopes a partition lookup to its cluster so a partition id from one cluster cannot
      * be read or mutated through another cluster's sub-resource path.
      */
-    Optional<SlurmPartitionEntity> findByPartitionIdAndSlurmCluster_ClusterId(String partitionId, String clusterId);
+    Optional<ClusterPartitionEntity> findByPartitionIdAndSlurmCluster_ClusterId(String partitionId, String clusterId);
 }
diff --git a/src/main/java/org/apache/airavata/compute/repository/SlurmClusterRepository.java b/src/main/java/org/apache/airavata/compute/repository/ClusterRepository.java
similarity index 59%
rename from src/main/java/org/apache/airavata/compute/repository/SlurmClusterRepository.java
rename to src/main/java/org/apache/airavata/compute/repository/ClusterRepository.java
index f551ce6dc6..fcd114c780 100644
--- a/src/main/java/org/apache/airavata/compute/repository/SlurmClusterRepository.java
+++ b/src/main/java/org/apache/airavata/compute/repository/ClusterRepository.java
@@ -1,11 +1,11 @@
 package org.apache.airavata.compute.repository;
 
-import org.apache.airavata.compute.model.SlurmClusterEntity;
+import org.apache.airavata.compute.model.ClusterEntity;
 import org.springframework.data.repository.ListCrudRepository;
 import org.springframework.stereotype.Repository;
 
 @Repository
-public interface SlurmClusterRepository extends ListCrudRepository<SlurmClusterEntity, String> {
+public interface ClusterRepository extends ListCrudRepository<ClusterEntity, String> {
 
     boolean existsByClusterName(String clusterName);
 }
diff --git a/src/main/java/org/apache/airavata/compute/repository/SlurmClusterCredentialRepository.java b/src/main/java/org/apache/airavata/compute/repository/SlurmClusterCredentialRepository.java
deleted file mode 100644
index 0e4abe1de3..0000000000
--- a/src/main/java/org/apache/airavata/compute/repository/SlurmClusterCredentialRepository.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.apache.airavata.compute.repository;
-
-import java.util.List;
-import org.apache.airavata.compute.model.SlurmClusterCredentialEntity;
-import org.springframework.data.repository.ListCrudRepository;
-import org.springframework.stereotype.Repository;
-
-@Repository
-public interface SlurmClusterCredentialRepository extends ListCrudRepository<SlurmClusterCredentialEntity, String> {
-
-    List<SlurmClusterCredentialEntity> findBySlurmCluster_ClusterId(String clusterId);
-
-    List<SlurmClusterCredentialEntity> findByUser_UserId(String userId);
-
-    List<SlurmClusterCredentialEntity> findByUser_UserIdAndSlurmCluster_ClusterId(String userId, String clusterId);
-}
diff --git a/src/main/java/org/apache/airavata/compute/service/SlurmClusterCredentialService.java b/src/main/java/org/apache/airavata/compute/service/ClusterCredentialService.java
similarity index 74%
rename from src/main/java/org/apache/airavata/compute/service/SlurmClusterCredentialService.java
rename to src/main/java/org/apache/airavata/compute/service/ClusterCredentialService.java
index 4ee3b16e0f..bd628db508 100644
--- a/src/main/java/org/apache/airavata/compute/service/SlurmClusterCredentialService.java
+++ b/src/main/java/org/apache/airavata/compute/service/ClusterCredentialService.java
@@ -1,13 +1,13 @@
 package org.apache.airavata.compute.service;
 
 import java.util.List;
-import org.apache.airavata.compute.dto.SlurmClusterCredentialRequestDto;
-import org.apache.airavata.compute.dto.SlurmClusterCredentialResponseDto;
-import org.apache.airavata.compute.mapper.SlurmClusterCredentialMapper;
-import org.apache.airavata.compute.model.SlurmClusterCredentialEntity;
-import org.apache.airavata.compute.model.SlurmClusterEntity;
-import org.apache.airavata.compute.repository.SlurmClusterCredentialRepository;
-import org.apache.airavata.compute.repository.SlurmClusterRepository;
+import org.apache.airavata.compute.dto.ClusterCredentialRequestDto;
+import org.apache.airavata.compute.dto.ClusterCredentialResponseDto;
+import org.apache.airavata.compute.mapper.ClusterCredentialMapper;
+import org.apache.airavata.compute.model.ClusterCredentialEntity;
+import org.apache.airavata.compute.model.ClusterEntity;
+import org.apache.airavata.compute.repository.ClusterCredentialRepository;
+import org.apache.airavata.compute.repository.ClusterRepository;
 import org.apache.airavata.credentials.model.SSHUserCredential;
 import org.apache.airavata.credentials.repository.SSHUserCredentialRepository;
 import org.apache.airavata.iam.model.UserEntity;
@@ -32,20 +32,20 @@ import org.springframework.web.server.ResponseStatusException;
  * organization-level resources those other services expose.
  */
 @Service
-public class SlurmClusterCredentialService {
+public class ClusterCredentialService {
 
-    private final SlurmClusterCredentialRepository credentialBindingRepository;
-    private final SlurmClusterRepository clusterRepository;
+    private final ClusterCredentialRepository credentialBindingRepository;
+    private final ClusterRepository clusterRepository;
     private final SSHUserCredentialRepository credentialRepository;
     private final UserRepository userRepository;
-    private final SlurmClusterCredentialMapper mapper;
+    private final ClusterCredentialMapper mapper;
 
-    public SlurmClusterCredentialService(
-            SlurmClusterCredentialRepository credentialBindingRepository,
-            SlurmClusterRepository clusterRepository,
+    public ClusterCredentialService(
+            ClusterCredentialRepository credentialBindingRepository,
+            ClusterRepository clusterRepository,
             SSHUserCredentialRepository credentialRepository,
             UserRepository userRepository,
-            SlurmClusterCredentialMapper mapper) {
+            ClusterCredentialMapper mapper) {
         this.credentialBindingRepository = credentialBindingRepository;
         this.clusterRepository = clusterRepository;
         this.credentialRepository = credentialRepository;
@@ -56,8 +56,8 @@ public class SlurmClusterCredentialService {
     /** Lists every binding across every user, optionally scoped to one cluster. */
     @PreAuthorize("hasAnyAuthority('ADMIN', 'SUPER_ADMIN')")
     @Transactional(readOnly = true)
-    public List<SlurmClusterCredentialResponseDto> getAllCredentials(String clusterId) {
-        List<SlurmClusterCredentialEntity> entities = clusterId == null
+    public List<ClusterCredentialResponseDto> getAllCredentials(String clusterId) {
+        List<ClusterCredentialEntity> entities = clusterId == null
                 ? credentialBindingRepository.findAll()
                 : credentialBindingRepository.findBySlurmCluster_ClusterId(clusterId);
         return entities.stream().map(mapper::toResponseDto).toList();
@@ -66,17 +66,17 @@ public class SlurmClusterCredentialService {
     /** Lists the caller's own bindings, optionally scoped to one cluster. */
     @PreAuthorize("isAuthenticated()")
     @Transactional(readOnly = true)
-    public List<SlurmClusterCredentialResponseDto> getMyCredentials(String clusterId) {
+    public List<ClusterCredentialResponseDto> getMyCredentials(String clusterId) {
         String userId = resolveCurrentUser().getUserId();
-        List<SlurmClusterCredentialEntity> entities = clusterId == null
+        List<ClusterCredentialEntity> entities = clusterId == null
                 ? credentialBindingRepository.findByUser_UserId(userId)
                 : credentialBindingRepository.findByUser_UserIdAndSlurmCluster_ClusterId(userId, clusterId);
         return entities.stream().map(mapper::toResponseDto).toList();
     }
 
     @Transactional(readOnly = true)
-    public SlurmClusterCredentialResponseDto getCredential(String id) {
-        SlurmClusterCredentialEntity entity = findOrThrow(id);
+    public ClusterCredentialResponseDto getCredential(String id) {
+        ClusterCredentialEntity entity = findOrThrow(id);
         requireSelfOrAdmin(entity);
         return mapper.toResponseDto(entity);
     }
@@ -84,8 +84,8 @@ public class SlurmClusterCredentialService {
     /** Any authenticated caller may bind a credential — this is a self-service setting. */
     @PreAuthorize("isAuthenticated()")
     @Transactional
-    public SlurmClusterCredentialResponseDto createCredential(SlurmClusterCredentialRequestDto request) {
-        SlurmClusterCredentialEntity entity = new SlurmClusterCredentialEntity();
+    public ClusterCredentialResponseDto createCredential(ClusterCredentialRequestDto request) {
+        ClusterCredentialEntity entity = new ClusterCredentialEntity();
         entity.setSlurmCluster(resolveCluster(request.getClusterId()));
         entity.setSshUserCredential(resolveCredential(request.getSshCredentialId()));
         entity.setUser(resolveCurrentUser());
@@ -94,8 +94,8 @@ public class SlurmClusterCredentialService {
 
     /** Ownership is immutable — only the cluster/credential references can change. */
     @Transactional
-    public SlurmClusterCredentialResponseDto updateCredential(String id, SlurmClusterCredentialRequestDto request) {
-        SlurmClusterCredentialEntity entity = findOrThrow(id);
+    public ClusterCredentialResponseDto updateCredential(String id, ClusterCredentialRequestDto request) {
+        ClusterCredentialEntity entity = findOrThrow(id);
         requireSelfOrAdmin(entity);
         entity.setSlurmCluster(resolveCluster(request.getClusterId()));
         entity.setSshUserCredential(resolveCredential(request.getSshCredentialId()));
@@ -104,19 +104,19 @@ public class SlurmClusterCredentialService {
 
     @Transactional
     public void deleteCredential(String id) {
-        SlurmClusterCredentialEntity entity = findOrThrow(id);
+        ClusterCredentialEntity entity = findOrThrow(id);
         requireSelfOrAdmin(entity);
         credentialBindingRepository.delete(entity);
     }
 
-    private SlurmClusterCredentialEntity findOrThrow(String id) {
+    private ClusterCredentialEntity findOrThrow(String id) {
         return credentialBindingRepository
                 .findById(id)
                 .orElseThrow(() ->
                         new ResponseStatusException(HttpStatus.NOT_FOUND, "Cluster credential binding not found: " + id));
     }
 
-    private SlurmClusterEntity resolveCluster(String clusterId) {
+    private ClusterEntity resolveCluster(String clusterId) {
         return clusterRepository
                 .findById(clusterId)
                 .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Cluster not found: " + clusterId));
@@ -144,7 +144,7 @@ public class SlurmClusterCredentialService {
                         HttpStatus.NOT_FOUND, "No user record found for authenticated principal: " + username));
     }
 
-    private void requireSelfOrAdmin(SlurmClusterCredentialEntity entity) {
+    private void requireSelfOrAdmin(ClusterCredentialEntity entity) {
         Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
         boolean isSelf = entity.getUser() != null && authentication.getName().equals(entity.getUser().getUserId());
         boolean isAdmin = authentication.getAuthorities().stream()
diff --git a/src/main/java/org/apache/airavata/compute/service/SlurmPartitionService.java b/src/main/java/org/apache/airavata/compute/service/ClusterPartitionService.java
similarity index 59%
rename from src/main/java/org/apache/airavata/compute/service/SlurmPartitionService.java
rename to src/main/java/org/apache/airavata/compute/service/ClusterPartitionService.java
index bbc1c40df1..83a027d6a0 100644
--- a/src/main/java/org/apache/airavata/compute/service/SlurmPartitionService.java
+++ b/src/main/java/org/apache/airavata/compute/service/ClusterPartitionService.java
@@ -1,13 +1,13 @@
 package org.apache.airavata.compute.service;
 
 import java.util.List;
-import org.apache.airavata.compute.dto.SlurmPartitionRequestDto;
-import org.apache.airavata.compute.dto.SlurmPartitionResponseDto;
-import org.apache.airavata.compute.mapper.SlurmPartitionMapper;
-import org.apache.airavata.compute.model.SlurmClusterEntity;
-import org.apache.airavata.compute.model.SlurmPartitionEntity;
-import org.apache.airavata.compute.repository.SlurmClusterRepository;
-import org.apache.airavata.compute.repository.SlurmPartitionRepository;
+import org.apache.airavata.compute.dto.ClusterPartitionRequestDto;
+import org.apache.airavata.compute.dto.ClusterPartitionResponseDto;
+import org.apache.airavata.compute.mapper.ClusterPartitionMapper;
+import org.apache.airavata.compute.model.ClusterEntity;
+import org.apache.airavata.compute.model.ClusterPartitionEntity;
+import org.apache.airavata.compute.repository.ClusterPartitionRepository;
+import org.apache.airavata.compute.repository.ClusterRepository;
 import org.springframework.http.HttpStatus;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.stereotype.Service;
@@ -22,28 +22,28 @@ import org.springframework.web.server.ResponseStatusException;
  * an accidental cross-cluster edit.
  *
  * <p>Partitions are persisted through their own repository rather than by mutating
- * {@link SlurmClusterEntity#getPartitions()}: the association is orphan-removing, so
+ * {@link ClusterEntity#getPartitions()}: the association is orphan-removing, so
  * touching that collection here would risk deleting rows this service never intended
  * to remove.
  */
 @Service
-public class SlurmPartitionService {
+public class ClusterPartitionService {
 
-    private final SlurmPartitionRepository partitionRepository;
-    private final SlurmClusterRepository clusterRepository;
-    private final SlurmPartitionMapper mapper;
+    private final ClusterPartitionRepository partitionRepository;
+    private final ClusterRepository clusterRepository;
+    private final ClusterPartitionMapper mapper;
 
-    public SlurmPartitionService(
-            SlurmPartitionRepository partitionRepository,
-            SlurmClusterRepository clusterRepository,
-            SlurmPartitionMapper mapper) {
+    public ClusterPartitionService(
+            ClusterPartitionRepository partitionRepository,
+            ClusterRepository clusterRepository,
+            ClusterPartitionMapper mapper) {
         this.partitionRepository = partitionRepository;
         this.clusterRepository = clusterRepository;
         this.mapper = mapper;
     }
 
     @Transactional(readOnly = true)
-    public List<SlurmPartitionResponseDto> getPartitions(String clusterId) {
+    public List<ClusterPartitionResponseDto> getPartitions(String clusterId) {
         requireCluster(clusterId);
         return partitionRepository.findBySlurmCluster_ClusterId(clusterId).stream()
                 .map(mapper::toResponseDto)
@@ -51,23 +51,23 @@ public class SlurmPartitionService {
     }
 
     @Transactional(readOnly = true)
-    public SlurmPartitionResponseDto getPartition(String clusterId, String partitionId) {
+    public ClusterPartitionResponseDto getPartition(String clusterId, String partitionId) {
         return mapper.toResponseDto(findOrThrow(clusterId, partitionId));
     }
 
     @PreAuthorize("hasAnyAuthority('ADMIN', 'SUPER_ADMIN')")
     @Transactional
-    public SlurmPartitionResponseDto createPartition(String clusterId, SlurmPartitionRequestDto request) {
-        SlurmPartitionEntity entity = mapper.toEntity(request);
+    public ClusterPartitionResponseDto createPartition(String clusterId, ClusterPartitionRequestDto request) {
+        ClusterPartitionEntity entity = mapper.toEntity(request);
         entity.setSlurmCluster(requireCluster(clusterId));
         return mapper.toResponseDto(partitionRepository.save(entity));
     }
 
     @PreAuthorize("hasAnyAuthority('ADMIN', 'SUPER_ADMIN')")
     @Transactional
-    public SlurmPartitionResponseDto updatePartition(
-            String clusterId, String partitionId, SlurmPartitionRequestDto request) {
-        SlurmPartitionEntity entity = findOrThrow(clusterId, partitionId);
+    public ClusterPartitionResponseDto updatePartition(
+            String clusterId, String partitionId, ClusterPartitionRequestDto request) {
+        ClusterPartitionEntity entity = findOrThrow(clusterId, partitionId);
         mapper.updateEntity(request, entity);
         return mapper.toResponseDto(partitionRepository.save(entity));
     }
@@ -78,13 +78,13 @@ public class SlurmPartitionService {
         partitionRepository.delete(findOrThrow(clusterId, partitionId));
     }
 
-    private SlurmClusterEntity requireCluster(String clusterId) {
+    private ClusterEntity requireCluster(String clusterId) {
         return clusterRepository
                 .findById(clusterId)
                 .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Cluster not found: " + clusterId));
     }
 
-    private SlurmPartitionEntity findOrThrow(String clusterId, String partitionId) {
+    private ClusterPartitionEntity findOrThrow(String clusterId, String partitionId) {
         return partitionRepository
                 .findByPartitionIdAndSlurmCluster_ClusterId(partitionId, clusterId)
                 .orElseThrow(() -> new ResponseStatusException(
diff --git a/src/main/java/org/apache/airavata/compute/service/SlurmClusterService.java b/src/main/java/org/apache/airavata/compute/service/ClusterService.java
similarity index 62%
rename from src/main/java/org/apache/airavata/compute/service/SlurmClusterService.java
rename to src/main/java/org/apache/airavata/compute/service/ClusterService.java
index 34c1eaeb67..c77d13aea7 100644
--- a/src/main/java/org/apache/airavata/compute/service/SlurmClusterService.java
+++ b/src/main/java/org/apache/airavata/compute/service/ClusterService.java
@@ -1,11 +1,11 @@
 package org.apache.airavata.compute.service;
 
 import java.util.List;
-import org.apache.airavata.compute.dto.SlurmClusterRequestDto;
-import org.apache.airavata.compute.dto.SlurmClusterResponseDto;
-import org.apache.airavata.compute.mapper.SlurmClusterMapper;
-import org.apache.airavata.compute.model.SlurmClusterEntity;
-import org.apache.airavata.compute.repository.SlurmClusterRepository;
+import org.apache.airavata.compute.dto.ClusterRequestDto;
+import org.apache.airavata.compute.dto.ClusterResponseDto;
+import org.apache.airavata.compute.mapper.ClusterMapper;
+import org.apache.airavata.compute.model.ClusterEntity;
+import org.apache.airavata.compute.repository.ClusterRepository;
 import org.springframework.http.HttpStatus;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.stereotype.Service;
@@ -22,37 +22,37 @@ import org.springframework.web.server.ResponseStatusException;
  * <p>Deleting a cluster cascades to its partitions, which are owned by it.
  */
 @Service
-public class SlurmClusterService {
+public class ClusterService {
 
-    private final SlurmClusterRepository clusterRepository;
-    private final SlurmClusterMapper mapper;
+    private final ClusterRepository clusterRepository;
+    private final ClusterMapper mapper;
 
-    public SlurmClusterService(SlurmClusterRepository clusterRepository, SlurmClusterMapper mapper) {
+    public ClusterService(ClusterRepository clusterRepository, ClusterMapper mapper) {
         this.clusterRepository = clusterRepository;
         this.mapper = mapper;
     }
 
     @Transactional(readOnly = true)
-    public List<SlurmClusterResponseDto> getAllClusters() {
+    public List<ClusterResponseDto> getAllClusters() {
         return clusterRepository.findAll().stream().map(mapper::toResponseDto).toList();
     }
 
     @Transactional(readOnly = true)
-    public SlurmClusterResponseDto getCluster(String clusterId) {
+    public ClusterResponseDto getCluster(String clusterId) {
         return mapper.toResponseDto(findOrThrow(clusterId));
     }
 
     @PreAuthorize("hasAnyAuthority('ADMIN', 'SUPER_ADMIN')")
     @Transactional
-    public SlurmClusterResponseDto createCluster(SlurmClusterRequestDto request) {
-        SlurmClusterEntity entity = mapper.toEntity(request);
+    public ClusterResponseDto createCluster(ClusterRequestDto request) {
+        ClusterEntity entity = mapper.toEntity(request);
         return mapper.toResponseDto(clusterRepository.save(entity));
     }
 
     @PreAuthorize("hasAnyAuthority('ADMIN', 'SUPER_ADMIN')")
     @Transactional
-    public SlurmClusterResponseDto updateCluster(String clusterId, SlurmClusterRequestDto request) {
-        SlurmClusterEntity entity = findOrThrow(clusterId);
+    public ClusterResponseDto updateCluster(String clusterId, ClusterRequestDto request) {
+        ClusterEntity entity = findOrThrow(clusterId);
         mapper.updateEntity(request, entity);
         return mapper.toResponseDto(clusterRepository.save(entity));
     }
@@ -63,7 +63,7 @@ public class SlurmClusterService {
         clusterRepository.delete(findOrThrow(clusterId));
     }
 
-    private SlurmClusterEntity findOrThrow(String clusterId) {
+    private ClusterEntity findOrThrow(String clusterId) {
         return clusterRepository
                 .findById(clusterId)
                 .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Cluster not found: " + clusterId));
diff --git a/src/main/java/org/apache/airavata/data/dto/SCPDataRequestDto.java b/src/main/java/org/apache/airavata/data/dto/SCPDataRequestDto.java
new file mode 100644
index 0000000000..f9b5e036a8
--- /dev/null
+++ b/src/main/java/org/apache/airavata/data/dto/SCPDataRequestDto.java
@@ -0,0 +1,68 @@
+package org.apache.airavata.data.dto;
+
+import jakarta.validation.constraints.NotBlank;
+
+/**
+ * Create/update payload for an SCP data registration.
+ *
+ * <p>There is no {@code ownerId} field: ownership is derived from the caller's access
+ * token, never from client input, so a caller cannot register data on another user's
+ * behalf. There is no {@code provisionStatus} field either: that is lifecycle state
+ * managed by {@code SCPDataService}, not something a client sets directly.
+ */
+public class SCPDataRequestDto {
+
+    @NotBlank(message = "Data name cannot be blank")
+    private String dataName;
+
+    private String dataDescription;
+
+    @NotBlank(message = "isFile cannot be blank")
+    private String isFile;
+
+    @NotBlank(message = "Path cannot be blank")
+    private String path;
+
+    @NotBlank(message = "Slurm cluster credential id cannot be blank")
+    private String slurmClusterCredentialId;
+
+    public String getDataName() {
+        return dataName;
+    }
+
+    public void setDataName(String dataName) {
+        this.dataName = dataName;
+    }
+
+    public String getDataDescription() {
+        return dataDescription;
+    }
+
+    public void setDataDescription(String dataDescription) {
+        this.dataDescription = dataDescription;
+    }
+
+    public String getIsFile() {
+        return isFile;
+    }
+
+    public void setIsFile(String isFile) {
+        this.isFile = isFile;
+    }
+
+    public String getPath() {
+        return path;
+    }
+
+    public void setPath(String path) {
+        this.path = path;
+    }
+
+    public String getSlurmClusterCredentialId() {
+        return slurmClusterCredentialId;
+    }
+
+    public void setSlurmClusterCredentialId(String slurmClusterCredentialId) {
+        this.slurmClusterCredentialId = slurmClusterCredentialId;
+    }
+}
diff --git a/src/main/java/org/apache/airavata/data/dto/SCPDataResponseDto.java b/src/main/java/org/apache/airavata/data/dto/SCPDataResponseDto.java
new file mode 100644
index 0000000000..0024b43888
--- /dev/null
+++ b/src/main/java/org/apache/airavata/data/dto/SCPDataResponseDto.java
@@ -0,0 +1,80 @@
+package org.apache.airavata.data.dto;
+
+import org.apache.airavata.data.model.DataProvisionStatus;
+
+/** Read view of an SCP data registration. */
+public class SCPDataResponseDto {
+
+    private String dataId;
+    private String dataName;
+    private String dataDescription;
+    private String isFile;
+    private String path;
+    private String slurmClusterCredentialId;
+    private DataProvisionStatus provisionStatus;
+    private String ownerId;
+
+    public String getDataId() {
+        return dataId;
+    }
+
+    public void setDataId(String dataId) {
+        this.dataId = dataId;
+    }
+
+    public String getDataName() {
+        return dataName;
+    }
+
+    public void setDataName(String dataName) {
+        this.dataName = dataName;
+    }
+
+    public String getDataDescription() {
+        return dataDescription;
+    }
+
+    public void setDataDescription(String dataDescription) {
+        this.dataDescription = dataDescription;
+    }
+
+    public String getIsFile() {
+        return isFile;
+    }
+
+    public void setIsFile(String isFile) {
+        this.isFile = isFile;
+    }
+
+    public String getPath() {
+        return path;
+    }
+
+    public void setPath(String path) {
+        this.path = path;
+    }
+
+    public String getSlurmClusterCredentialId() {
+        return slurmClusterCredentialId;
+    }
+
+    public void setSlurmClusterCredentialId(String slurmClusterCredentialId) {
+        this.slurmClusterCredentialId = slurmClusterCredentialId;
+    }
+
+    public DataProvisionStatus getProvisionStatus() {
+        return provisionStatus;
+    }
+
+    public void setProvisionStatus(DataProvisionStatus provisionStatus) {
+        this.provisionStatus = provisionStatus;
+    }
+
+    public String getOwnerId() {
+        return ownerId;
+    }
+
+    public void setOwnerId(String ownerId) {
+        this.ownerId = ownerId;
+    }
+}
diff --git a/src/main/java/org/apache/airavata/data/mapper/SCPDataMapper.java b/src/main/java/org/apache/airavata/data/mapper/SCPDataMapper.java
new file mode 100644
index 0000000000..47a849fb22
--- /dev/null
+++ b/src/main/java/org/apache/airavata/data/mapper/SCPDataMapper.java
@@ -0,0 +1,37 @@
+package org.apache.airavata.data.mapper;
+
+import org.apache.airavata.data.dto.SCPDataRequestDto;
+import org.apache.airavata.data.dto.SCPDataResponseDto;
+import org.apache.airavata.data.model.SCPDataEntity;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.MappingTarget;
+import org.mapstruct.ReportingPolicy;
+
+/**
+ * Entity/DTO conversion for SCP data registrations.
+ *
+ * <p>The Slurm cluster credential and the owner are associations resolved by
+ * {@code SCPDataService} from the request DTO's id and the caller's access token, so
+ * neither is ever mapped straight off the request. {@code provisionStatus} is lifecycle
+ * state the service manages directly, so it is ignored here too.
+ */
+@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
+public interface SCPDataMapper {
+
+    @Mapping(target = "slurmClusterCredentialId", source = "slurmClusterCredential.clusterCredentialId")
+    @Mapping(target = "ownerId", source = "owner.userId")
+    SCPDataResponseDto toResponseDto(SCPDataEntity entity);
+
+    @Mapping(target = "dataId", ignore = true)
+    @Mapping(target = "slurmClusterCredential", ignore = true)
+    @Mapping(target = "owner", ignore = true)
+    @Mapping(target = "provisionStatus", ignore = true)
+    SCPDataEntity toEntity(SCPDataRequestDto dto);
+
+    @Mapping(target = "dataId", ignore = true)
+    @Mapping(target = "slurmClusterCredential", ignore = true)
+    @Mapping(target = "owner", ignore = true)
+    @Mapping(target = "provisionStatus", ignore = true)
+    void updateEntity(SCPDataRequestDto dto, @MappingTarget SCPDataEntity entity);
+}
diff --git a/src/main/java/org/apache/airavata/data/model/DataProvisionStatus.java b/src/main/java/org/apache/airavata/data/model/DataProvisionStatus.java
new file mode 100644
index 0000000000..249cae9e0d
--- /dev/null
+++ b/src/main/java/org/apache/airavata/data/model/DataProvisionStatus.java
@@ -0,0 +1,10 @@
+package org.apache.airavata.data.model;
+
+public enum DataProvisionStatus {
+    REGISTERD,
+    PROVISIONING,
+    PROVISIONED,
+    DEPROVISIONING,
+    DEPROVISIONED,
+    FAILED
+}
diff --git a/src/main/java/org/apache/airavata/data/model/SCPDataEntity.java b/src/main/java/org/apache/airavata/data/model/SCPDataEntity.java
new file mode 100644
index 0000000000..0be97ab0db
--- /dev/null
+++ b/src/main/java/org/apache/airavata/data/model/SCPDataEntity.java
@@ -0,0 +1,102 @@
+package org.apache.airavata.data.model;
+
+import jakarta.persistence.ForeignKey;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+
+import org.apache.airavata.compute.model.ClusterCredentialEntity;
+import org.apache.airavata.iam.model.UserEntity;
+
+import jakarta.persistence.Entity;
+
+@Entity
+public class SCPDataEntity {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.UUID)
+    private String dataId;
+
+    private String dataName;
+    private String dataDescription;
+    private String isFile;
+    private String path;
+
+    @ManyToOne
+    @JoinColumn(
+            name = "slurm_cluster_credential_id",
+            foreignKey = @ForeignKey(name = "fk_scp_data_slurm_cluster_credential"))
+    private ClusterCredentialEntity slurmClusterCredential;
+
+    private DataProvisionStatus provisionStatus;
+
+    @ManyToOne
+    @JoinColumn(name = "user_id", foreignKey = @ForeignKey(name = "fk_scp_data_user"))
+    private UserEntity owner;
+
+    public ClusterCredentialEntity getSlurmClusterCredential() {
+        return slurmClusterCredential;
+    }
+
+    public void setSlurmClusterCredential(ClusterCredentialEntity slurmClusterCredential) {
+        this.slurmClusterCredential = slurmClusterCredential;
+    }
+
+    public UserEntity getOwner() {
+        return owner;
+    }
+
+    public void setOwner(UserEntity owner) {
+        this.owner = owner;
+    }
+
+    public String getDataId() {
+        return dataId;
+    }
+
+    public void setDataId(String dataId) {
+        this.dataId = dataId;
+    }
+
+    public String getDataName() {
+        return dataName;
+    }
+
+    public void setDataName(String dataName) {
+        this.dataName = dataName;
+    }
+
+    public String getDataDescription() {
+        return dataDescription;
+    }
+
+    public void setDataDescription(String dataDescription) {
+        this.dataDescription = dataDescription;
+    }
+
+    public String getIsFile() {
+        return isFile;
+    }
+
+    public void setIsFile(String isFile) {
+        this.isFile = isFile;
+    }
+
+    public String getPath() {
+        return path;
+    }
+
+    public void setPath(String path) {
+        this.path = path;
+    }
+
+    public DataProvisionStatus getProvisionStatus() {
+        return provisionStatus;
+    }
+
+    public void setProvisionStatus(DataProvisionStatus provisionStatus) {
+        this.provisionStatus = provisionStatus;
+    }
+}
diff --git a/src/main/java/org/apache/airavata/data/repository/SCPDataRepository.java b/src/main/java/org/apache/airavata/data/repository/SCPDataRepository.java
new file mode 100644
index 0000000000..10ce4d8e50
--- /dev/null
+++ b/src/main/java/org/apache/airavata/data/repository/SCPDataRepository.java
@@ -0,0 +1,12 @@
+package org.apache.airavata.data.repository;
+
+import java.util.List;
+import org.apache.airavata.data.model.SCPDataEntity;
+import org.springframework.data.repository.ListCrudRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface SCPDataRepository extends ListCrudRepository<SCPDataEntity, String> {
+
+    List<SCPDataEntity> findByOwner_UserId(String userId);
+}
diff --git a/src/main/java/org/apache/airavata/data/service/SCPDataService.java b/src/main/java/org/apache/airavata/data/service/SCPDataService.java
new file mode 100644
index 0000000000..a36969129a
--- /dev/null
+++ b/src/main/java/org/apache/airavata/data/service/SCPDataService.java
@@ -0,0 +1,138 @@
+package org.apache.airavata.data.service;
+
+import java.util.List;
+import org.apache.airavata.compute.model.ClusterCredentialEntity;
+import org.apache.airavata.compute.repository.ClusterCredentialRepository;
+import org.apache.airavata.data.dto.SCPDataRequestDto;
+import org.apache.airavata.data.dto.SCPDataResponseDto;
+import org.apache.airavata.data.mapper.SCPDataMapper;
+import org.apache.airavata.data.model.DataProvisionStatus;
+import org.apache.airavata.data.model.SCPDataEntity;
+import org.apache.airavata.data.repository.SCPDataRepository;
+import org.apache.airavata.iam.model.UserEntity;
+import org.apache.airavata.iam.repository.UserRepository;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.server.ResponseStatusException;
+
+/**
+ * CRUD for SCP data registrations.
+ *
+ * <p>Ownership is never taken from client input: {@code createData} derives the owning
+ * user from the caller's access token. Single-record reads and all writes are restricted
+ * to the owning user or an admin, matching the model used by
+ * {@code ClusterCredentialService} — a data registration is a per-user resource, not
+ * a shared, organization-level one.
+ */
+@Service
+public class SCPDataService {
+
+    private final SCPDataRepository dataRepository;
+    private final ClusterCredentialRepository credentialRepository;
+    private final UserRepository userRepository;
+    private final SCPDataMapper mapper;
+
+    public SCPDataService(
+            SCPDataRepository dataRepository,
+            ClusterCredentialRepository credentialRepository,
+            UserRepository userRepository,
+            SCPDataMapper mapper) {
+        this.dataRepository = dataRepository;
+        this.credentialRepository = credentialRepository;
+        this.userRepository = userRepository;
+        this.mapper = mapper;
+    }
+
+    /** Lists every data registration across every user. */
+    @PreAuthorize("hasAnyAuthority('ADMIN', 'SUPER_ADMIN')")
+    @Transactional(readOnly = true)
+    public List<SCPDataResponseDto> getAllData() {
+        return dataRepository.findAll().stream().map(mapper::toResponseDto).toList();
+    }
+
+    /** Lists the caller's own data registrations. */
+    @PreAuthorize("isAuthenticated()")
+    @Transactional(readOnly = true)
+    public List<SCPDataResponseDto> getMyData() {
+        String userId = resolveCurrentUser().getUserId();
+        return dataRepository.findByOwner_UserId(userId).stream().map(mapper::toResponseDto).toList();
+    }
+
+    @Transactional(readOnly = true)
+    public SCPDataResponseDto getData(String id) {
+        SCPDataEntity entity = findOrThrow(id);
+        requireSelfOrAdmin(entity);
+        return mapper.toResponseDto(entity);
+    }
+
+    /** Any authenticated caller may register data — this is a self-service action. */
+    @PreAuthorize("isAuthenticated()")
+    @Transactional
+    public SCPDataResponseDto createData(SCPDataRequestDto request) {
+        SCPDataEntity entity = mapper.toEntity(request);
+        entity.setSlurmClusterCredential(resolveCredential(request.getSlurmClusterCredentialId()));
+        entity.setOwner(resolveCurrentUser());
+        entity.setProvisionStatus(DataProvisionStatus.REGISTERD);
+        return mapper.toResponseDto(dataRepository.save(entity));
+    }
+
+    /** Ownership is immutable — only the descriptive fields and credential can change. */
+    @Transactional
+    public SCPDataResponseDto updateData(String id, SCPDataRequestDto request) {
+        SCPDataEntity entity = findOrThrow(id);
+        requireSelfOrAdmin(entity);
+        mapper.updateEntity(request, entity);
+        entity.setSlurmClusterCredential(resolveCredential(request.getSlurmClusterCredentialId()));
+        return mapper.toResponseDto(dataRepository.save(entity));
+    }
+
+    @Transactional
+    public void deleteData(String id) {
+        SCPDataEntity entity = findOrThrow(id);
+        requireSelfOrAdmin(entity);
+        dataRepository.delete(entity);
+    }
+
+    private SCPDataEntity findOrThrow(String id) {
+        return dataRepository
+                .findById(id)
+                .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "SCP data not found: " + id));
+    }
+
+    private ClusterCredentialEntity resolveCredential(String credentialId) {
+        return credentialRepository
+                .findById(credentialId)
+                .orElseThrow(() -> new ResponseStatusException(
+                        HttpStatus.NOT_FOUND, "Slurm cluster credential not found: " + credentialId));
+    }
+
+    /**
+     * Resolves the caller's {@link UserEntity} from the principal name that
+     * {@code UserRoleOpaqueTokenIntrospector} put on the security context — the same
+     * identifier used as {@code UserEntity.userId} (see {@code UserService.getUserById}'s
+     * "isSelf" check for the other place this equivalence is relied on).
+     */
+    private UserEntity resolveCurrentUser() {
+        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+        String username = authentication.getName();
+        return userRepository
+                .findById(username)
+                .orElseThrow(() -> new ResponseStatusException(
+                        HttpStatus.NOT_FOUND, "No user record found for authenticated principal: " + username));
+    }
+
+    private void requireSelfOrAdmin(SCPDataEntity entity) {
+        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+        boolean isSelf = entity.getOwner() != null && authentication.getName().equals(entity.getOwner().getUserId());
+        boolean isAdmin = authentication.getAuthorities().stream()
+                .anyMatch(auth -> auth.getAuthority().equals("ADMIN") || auth.getAuthority().equals("SUPER_ADMIN"));
+        if (!isSelf && !isAdmin) {
+            throw new AccessDeniedException("Access denied: you may only access your own SCP data");
+        }
+    }
+}