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

yasith pushed a commit to branch AIRAVATA-3981/integration-health-check
in repository https://gitbox.apache.org/repos/asf/airavata.git

commit a25464a1c31d93f04a33c8f78e57d7a9cc625f09
Author: yasithdev <[email protected]>
AuthorDate: Thu Mar 26 15:41:00 2026 -0500

    chore: final cleanup — gitignore docs/superpowers, fix health endpoint 
format
    
    - Wrap /health/services response in {"services": {...}} per spec
    - Update ServiceHealthEndpointTest and BackgroundServiceHealthTest to
      unwrap the "services" key before asserting on service entries
    - Add docs/superpowers/ to .gitignore and remove already-committed files
      from git tracking (local copies preserved)
---
 .gitignore                                         |    2 +
 .../patform/monitoring/MonitoringServer.java       |    2 +-
 ...2026-03-26-airavata-thrift-server-extraction.md | 1090 --------------------
 ...-26-airavata-thrift-server-extraction-design.md |  190 ----
 .../integration/BackgroundServiceHealthTest.java   |    4 +-
 .../integration/ServiceHealthEndpointTest.java     |    8 +-
 6 files changed, 12 insertions(+), 1284 deletions(-)

diff --git a/.gitignore b/.gitignore
index 6a9a2b896a..a9c37a7d2d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -66,3 +66,5 @@ keystores/airavata.p12
 keystores/aes.p12
 modules/*/distribution/
 modules/*/*/distribution/
+
+docs/superpowers/
diff --git 
a/airavata-api/src/main/java/org/apache/airavata/patform/monitoring/MonitoringServer.java
 
b/airavata-api/src/main/java/org/apache/airavata/patform/monitoring/MonitoringServer.java
index 1f7bac390d..43fa6f7afe 100644
--- 
a/airavata-api/src/main/java/org/apache/airavata/patform/monitoring/MonitoringServer.java
+++ 
b/airavata-api/src/main/java/org/apache/airavata/patform/monitoring/MonitoringServer.java
@@ -137,7 +137,7 @@ public class MonitoringServer implements IServer {
         try {
             Map<String, ServiceStatus> statuses =
                     serviceRegistry != null ? serviceRegistry.getStatuses() : 
Map.of();
-            sendJson(exchange, 200, statuses);
+            sendJson(exchange, 200, Map.of("services", statuses));
         } catch (Exception e) {
             logger.error("Error serving /health/services", e);
             sendResponse(exchange, 500, "Internal Server Error");
diff --git 
a/docs/superpowers/plans/2026-03-26-airavata-thrift-server-extraction.md 
b/docs/superpowers/plans/2026-03-26-airavata-thrift-server-extraction.md
deleted file mode 100644
index 837d304414..0000000000
--- a/docs/superpowers/plans/2026-03-26-airavata-thrift-server-extraction.md
+++ /dev/null
@@ -1,1090 +0,0 @@
-# Airavata Thrift Server Extraction Implementation Plan
-
-> **For agentic workers:** REQUIRED SUB-SKILL: Use 
superpowers:subagent-driven-development (recommended) or 
superpowers:executing-plans to implement this plan task-by-task. Steps use 
checkbox (`- [ ]`) syntax for tracking.
-
-**Goal:** Extract all thrift server concerns from `airavata-api` into a new 
`airavata-thrift-server` Maven module, introduce proto DTOs in `airavata-api`, 
and set up MapStruct mapping at the thrift handler boundary.
-
-**Architecture:** `airavata-thrift-server` depends on `airavata-api`. Thrift 
IDL lives in `airavata-thrift-server/src/main/thrift/`. Server bootstrap 
(AiravataServer), the main API handler (AiravataServerHandler), profile 
handlers, OrchestratorServerHandler, ThriftAdapter, and Constants move to 
`airavata-thrift-server`. Data-access handlers (RegistryServerHandler, 
SharingRegistryServerHandler, CredentialStoreServerHandler) stay in 
`airavata-api` because services depend on them directly — [...]
-
-**Tech Stack:** Maven, Apache Thrift 0.22.0, Protocol Buffers 4.30.1, 
MapStruct 1.6.3, protobuf-maven-plugin 3.10.2
-
-**Spec:** 
`docs/superpowers/specs/2026-03-26-airavata-thrift-server-extraction-design.md`
-
----
-
-## File Structure
-
-### New files (airavata-thrift-server)
-
-| File | Responsibility |
-|------|---------------|
-| `airavata-thrift-server/pom.xml` | Module POM — depends on airavata-api, 
libthrift, MapStruct |
-| `airavata-thrift-server/src/main/thrift/**` | Moved from 
`thrift-interface-descriptions/` — all IDL files |
-| 
`airavata-thrift-server/src/main/java/org/apache/airavata/api/server/AiravataServer.java`
 | Moved — thrift server bootstrap |
-| 
`airavata-thrift-server/src/main/java/org/apache/airavata/api/server/util/Constants.java`
 | Moved — server config constants |
-| 
`airavata-thrift-server/src/main/java/org/apache/airavata/api/server/handler/AiravataServerHandler.java`
 | Moved — main API thrift handler |
-| 
`airavata-thrift-server/src/main/java/org/apache/airavata/api/server/handler/ThriftAdapter.java`
 | Moved — thrift error translation |
-| 
`airavata-thrift-server/src/main/java/org/apache/airavata/service/profile/handlers/UserProfileServiceHandler.java`
 | Moved |
-| 
`airavata-thrift-server/src/main/java/org/apache/airavata/service/profile/handlers/TenantProfileServiceHandler.java`
 | Moved |
-| 
`airavata-thrift-server/src/main/java/org/apache/airavata/service/profile/handlers/IamAdminServicesHandler.java`
 | Moved |
-| 
`airavata-thrift-server/src/main/java/org/apache/airavata/service/profile/handlers/GroupManagerServiceHandler.java`
 | Moved |
-| 
`airavata-thrift-server/src/main/java/org/apache/airavata/orchestrator/server/OrchestratorServerHandler.java`
 | Moved |
-
-### New files (airavata-api — proto)
-
-| File | Responsibility |
-|------|---------------|
-| 
`airavata-api/src/main/proto/org/apache/airavata/model/workspace/workspace.proto`
 | Proto mirror of workspace_model.thrift |
-| 
`airavata-api/src/main/proto/org/apache/airavata/model/experiment/experiment.proto`
 | Proto mirror of experiment_model.thrift |
-| `airavata-api/src/main/proto/org/apache/airavata/model/status/status.proto` 
| Proto mirror of status_models.thrift |
-| ... (one proto per thrift data-model file — 28 total) | Mechanical 1:1 
translation |
-| 
`airavata-api/src/main/proto/org/apache/airavata/model/security/security.proto` 
| Proto mirror of security_model.thrift |
-| `airavata-api/src/main/proto/org/apache/airavata/model/error/errors.proto` | 
Proto mirror of airavata_errors.thrift |
-| 
`airavata-api/src/main/proto/org/apache/airavata/model/commons/commons.proto` | 
Proto mirror of airavata_commons.thrift |
-
-### Modified files
-
-| File | Change |
-|------|--------|
-| `pom.xml` (root) | Add `airavata-thrift-server` module before `airavata-api` 
in module order |
-| `airavata-api/pom.xml` | Update thrift compiler path, add protobuf-java + 
protobuf-maven-plugin, add MapStruct deps |
-
-### Deleted files (from airavata-api)
-
-| File | Reason |
-|------|--------|
-| 
`airavata-api/src/main/java/org/apache/airavata/api/server/AiravataServer.java` 
| Moved |
-| 
`airavata-api/src/main/java/org/apache/airavata/api/server/util/Constants.java` 
| Moved |
-| 
`airavata-api/src/main/java/org/apache/airavata/api/server/handler/AiravataServerHandler.java`
 | Moved |
-| 
`airavata-api/src/main/java/org/apache/airavata/api/server/handler/ThriftAdapter.java`
 | Moved |
-| 
`airavata-api/src/main/java/org/apache/airavata/service/profile/handlers/UserProfileServiceHandler.java`
 | Moved |
-| 
`airavata-api/src/main/java/org/apache/airavata/service/profile/handlers/TenantProfileServiceHandler.java`
 | Moved |
-| 
`airavata-api/src/main/java/org/apache/airavata/service/profile/handlers/IamAdminServicesHandler.java`
 | Moved |
-| 
`airavata-api/src/main/java/org/apache/airavata/service/profile/handlers/GroupManagerServiceHandler.java`
 | Moved |
-| 
`airavata-api/src/main/java/org/apache/airavata/orchestrator/server/OrchestratorServerHandler.java`
 | Moved |
-| `thrift-interface-descriptions/` | Moved to 
airavata-thrift-server/src/main/thrift/ |
-
----
-
-### Task 1: Create git worktree
-
-**Files:**
-- None (git operation)
-
-- [ ] **Step 1: Create worktree branch**
-
-```bash
-cd /Users/yasith/code/artisan/airavata
-git worktree add ../airavata-thrift-extraction -b feat/thrift-server-extraction
-```
-
-- [ ] **Step 2: Verify worktree**
-
-```bash
-cd /Users/yasith/code/artisan/airavata-thrift-extraction
-git branch --show-current
-```
-
-Expected: `feat/thrift-server-extraction`
-
-All subsequent tasks run inside 
`/Users/yasith/code/artisan/airavata-thrift-extraction/`.
-
----
-
-### Task 2: Create airavata-thrift-server Maven module
-
-**Files:**
-- Create: `airavata-thrift-server/pom.xml`
-- Modify: `pom.xml` (root)
-
-- [ ] **Step 1: Create module directory**
-
-```bash
-mkdir -p airavata-thrift-server/src/main/java
-```
-
-- [ ] **Step 2: Write airavata-thrift-server/pom.xml**
-
-```xml
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0";
-  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
-
-  <modelVersion>4.0.0</modelVersion>
-
-  <parent>
-    <groupId>org.apache.airavata</groupId>
-    <artifactId>airavata</artifactId>
-    <version>0.21-SNAPSHOT</version>
-    <relativePath>../pom.xml</relativePath>
-  </parent>
-
-  <artifactId>airavata-thrift-server</artifactId>
-  <packaging>jar</packaging>
-  <name>Airavata Thrift Server</name>
-
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.airavata</groupId>
-      <artifactId>airavata-api</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.thrift</groupId>
-      <artifactId>libthrift</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-api</artifactId>
-    </dependency>
-  </dependencies>
-</project>
-```
-
-- [ ] **Step 3: Add module to root pom.xml**
-
-In `pom.xml`, add `airavata-thrift-server` AFTER `airavata-api` in the 
`<modules>` block (it depends on airavata-api):
-
-```xml
-    <modules>
-        <module>airavata-api</module>
-        <module>airavata-thrift-server</module>
-        <module>modules/file-server</module>
-        <module>modules/agent-framework/agent-service</module>
-        <module>modules/research-framework/research-service</module>
-        <module>modules/restproxy</module>
-        <module>modules/ide-integration</module>
-    </modules>
-```
-
-- [ ] **Step 4: Verify module resolves**
-
-```bash
-mvn validate -pl airavata-thrift-server -am --quiet
-```
-
-Expected: BUILD SUCCESS (no compilation yet, just POM validation)
-
-- [ ] **Step 5: Commit**
-
-```bash
-git add airavata-thrift-server/pom.xml pom.xml
-git commit -m "feat: add airavata-thrift-server Maven module scaffold"
-```
-
----
-
-### Task 3: Move thrift IDL files
-
-**Files:**
-- Move: `thrift-interface-descriptions/` → 
`airavata-thrift-server/src/main/thrift/`
-- Modify: `airavata-api/pom.xml` (update thrift compiler path)
-
-- [ ] **Step 1: Move the directory**
-
-```bash
-git mv thrift-interface-descriptions airavata-thrift-server/src/main/thrift
-```
-
-- [ ] **Step 2: Update thrift compiler path in airavata-api/pom.xml**
-
-In `airavata-api/pom.xml`, find the `maven-antrun-plugin` execution 
`generate-thrift-sources` and change the thrift input path from:
-
-```xml
-<arg 
value="${project.basedir}/../thrift-interface-descriptions/stubs_java.thrift" />
-```
-
-to:
-
-```xml
-<arg 
value="${project.basedir}/../airavata-thrift-server/src/main/thrift/stubs_java.thrift"
 />
-```
-
-- [ ] **Step 3: Verify thrift compilation still works**
-
-```bash
-mvn generate-sources -pl airavata-api --quiet
-ls 
airavata-api/target/generated-sources/thrift/org/apache/airavata/api/Airavata.java
-```
-
-Expected: file exists (thrift compiler found the moved IDL and generated code)
-
-- [ ] **Step 4: Commit**
-
-```bash
-git add -A
-git commit -m "refactor: move thrift IDL to 
airavata-thrift-server/src/main/thrift"
-```
-
----
-
-### Task 4: Move server bootstrap to airavata-thrift-server
-
-**Files:**
-- Move: 
`airavata-api/src/main/java/org/apache/airavata/api/server/AiravataServer.java` 
→ 
`airavata-thrift-server/src/main/java/org/apache/airavata/api/server/AiravataServer.java`
-- Move: 
`airavata-api/src/main/java/org/apache/airavata/api/server/util/Constants.java` 
→ 
`airavata-thrift-server/src/main/java/org/apache/airavata/api/server/util/Constants.java`
-
-- [ ] **Step 1: Create target directories**
-
-```bash
-mkdir -p 
airavata-thrift-server/src/main/java/org/apache/airavata/api/server/util
-```
-
-- [ ] **Step 2: Move AiravataServer.java**
-
-```bash
-git mv 
airavata-api/src/main/java/org/apache/airavata/api/server/AiravataServer.java \
-      
airavata-thrift-server/src/main/java/org/apache/airavata/api/server/AiravataServer.java
-```
-
-- [ ] **Step 3: Move Constants.java**
-
-```bash
-git mv 
airavata-api/src/main/java/org/apache/airavata/api/server/util/Constants.java \
-      
airavata-thrift-server/src/main/java/org/apache/airavata/api/server/util/Constants.java
-```
-
-Note: `Constants.java` contains `API_SERVER_PORT`, `API_SERVER_HOST`, 
`API_SERVER_MIN_THREADS` — used only by `AiravataServer.java`. The 
`ThriftAdapter.java` imports `org.apache.airavata.common.utils.Constants` (a 
different class in commons), NOT this one.
-
-- [ ] **Step 4: Commit**
-
-```bash
-git add -A
-git commit -m "refactor: move AiravataServer and Constants to 
airavata-thrift-server"
-```
-
----
-
-### Task 5: Move AiravataServerHandler and ThriftAdapter
-
-**Files:**
-- Move: 
`airavata-api/src/main/java/org/apache/airavata/api/server/handler/AiravataServerHandler.java`
 → `airavata-thrift-server/...`
-- Move: 
`airavata-api/src/main/java/org/apache/airavata/api/server/handler/ThriftAdapter.java`
 → `airavata-thrift-server/...`
-
-- [ ] **Step 1: Create target directory**
-
-```bash
-mkdir -p 
airavata-thrift-server/src/main/java/org/apache/airavata/api/server/handler
-```
-
-- [ ] **Step 2: Move both files**
-
-```bash
-git mv 
airavata-api/src/main/java/org/apache/airavata/api/server/handler/AiravataServerHandler.java
 \
-      
airavata-thrift-server/src/main/java/org/apache/airavata/api/server/handler/AiravataServerHandler.java
-
-git mv 
airavata-api/src/main/java/org/apache/airavata/api/server/handler/ThriftAdapter.java
 \
-      
airavata-thrift-server/src/main/java/org/apache/airavata/api/server/handler/ThriftAdapter.java
-```
-
-No import changes needed — packages stay the same, and 
`airavata-thrift-server` depends on `airavata-api` which provides all service 
classes and handler classes they reference.
-
-- [ ] **Step 3: Commit**
-
-```bash
-git add -A
-git commit -m "refactor: move AiravataServerHandler and ThriftAdapter to 
airavata-thrift-server"
-```
-
----
-
-### Task 6: Move profile handlers and OrchestratorServerHandler
-
-**Files:**
-- Move: 
`airavata-api/src/main/java/org/apache/airavata/service/profile/handlers/UserProfileServiceHandler.java`
-- Move: 
`airavata-api/src/main/java/org/apache/airavata/service/profile/handlers/TenantProfileServiceHandler.java`
-- Move: 
`airavata-api/src/main/java/org/apache/airavata/service/profile/handlers/IamAdminServicesHandler.java`
-- Move: 
`airavata-api/src/main/java/org/apache/airavata/service/profile/handlers/GroupManagerServiceHandler.java`
-- Move: 
`airavata-api/src/main/java/org/apache/airavata/orchestrator/server/OrchestratorServerHandler.java`
-
-- [ ] **Step 1: Create target directories**
-
-```bash
-mkdir -p 
airavata-thrift-server/src/main/java/org/apache/airavata/service/profile/handlers
-mkdir -p 
airavata-thrift-server/src/main/java/org/apache/airavata/orchestrator/server
-```
-
-- [ ] **Step 2: Move profile handlers**
-
-```bash
-git mv 
airavata-api/src/main/java/org/apache/airavata/service/profile/handlers/UserProfileServiceHandler.java
 \
-      
airavata-thrift-server/src/main/java/org/apache/airavata/service/profile/handlers/UserProfileServiceHandler.java
-
-git mv 
airavata-api/src/main/java/org/apache/airavata/service/profile/handlers/TenantProfileServiceHandler.java
 \
-      
airavata-thrift-server/src/main/java/org/apache/airavata/service/profile/handlers/TenantProfileServiceHandler.java
-
-git mv 
airavata-api/src/main/java/org/apache/airavata/service/profile/handlers/IamAdminServicesHandler.java
 \
-      
airavata-thrift-server/src/main/java/org/apache/airavata/service/profile/handlers/IamAdminServicesHandler.java
-
-git mv 
airavata-api/src/main/java/org/apache/airavata/service/profile/handlers/GroupManagerServiceHandler.java
 \
-      
airavata-thrift-server/src/main/java/org/apache/airavata/service/profile/handlers/GroupManagerServiceHandler.java
-```
-
-- [ ] **Step 3: Move OrchestratorServerHandler**
-
-```bash
-git mv 
airavata-api/src/main/java/org/apache/airavata/orchestrator/server/OrchestratorServerHandler.java
 \
-      
airavata-thrift-server/src/main/java/org/apache/airavata/orchestrator/server/OrchestratorServerHandler.java
-```
-
-- [ ] **Step 4: Commit**
-
-```bash
-git add -A
-git commit -m "refactor: move profile handlers and OrchestratorServerHandler 
to airavata-thrift-server"
-```
-
----
-
-### Task 7: Verify full build compiles
-
-**Files:**
-- Possibly modify: `airavata-thrift-server/pom.xml` (if missing deps surface)
-
-- [ ] **Step 1: Build airavata-api (should still compile — only lost handler 
classes it no longer owns)**
-
-```bash
-mvn compile -pl airavata-api --quiet 2>&1 | tail -5
-```
-
-Expected: BUILD SUCCESS. If any code in `airavata-api` still imports the moved 
handler classes, identify the files and update imports or remove dead 
references.
-
-- [ ] **Step 2: Build airavata-thrift-server**
-
-```bash
-mvn compile -pl airavata-thrift-server -am 2>&1 | tail -20
-```
-
-Expected: BUILD SUCCESS. If compilation fails due to missing dependencies, add 
them to `airavata-thrift-server/pom.xml`. Likely candidates:
-- Profile service CPI constants (thrift generated — already available via 
airavata-api dependency)
-- Helix/ZooKeeper classes used by OrchestratorServerHandler
-- Messaging classes used by AiravataServerHandler
-- Monitoring/background service classes used by AiravataServer
-
-For each missing dependency, add it to `airavata-thrift-server/pom.xml`:
-
-```xml
-<!-- Add as needed based on compilation errors -->
-<dependency>
-  <groupId>org.apache.helix</groupId>
-  <artifactId>helix-core</artifactId>
-</dependency>
-<dependency>
-  <groupId>io.prometheus</groupId>
-  <artifactId>simpleclient</artifactId>
-</dependency>
-<!-- etc. -->
-```
-
-- [ ] **Step 3: Fix any compilation errors**
-
-Iterate: read error → add dependency or fix import → rebuild. Continue until 
BUILD SUCCESS for both modules.
-
-- [ ] **Step 4: Run tests**
-
-```bash
-mvn test -pl airavata-api --quiet 2>&1 | tail -5
-```
-
-Expected: Tests pass (no behavioral changes, only file moves).
-
-- [ ] **Step 5: Commit**
-
-```bash
-git add -A
-git commit -m "fix: resolve airavata-thrift-server compilation dependencies"
-```
-
----
-
-### Task 8: Create proto files — workspace model (representative example)
-
-**Files:**
-- Create: 
`airavata-api/src/main/proto/org/apache/airavata/model/workspace/workspace.proto`
-
-This task demonstrates the proto translation pattern. All subsequent proto 
files follow the same rules.
-
-**Translation rules (thrift → proto):**
-- `namespace java X` → `option java_package = "X"; option java_outer_classname 
= "XProtos";`
-- `struct` → `message`
-- `enum` → `enum` (add `UNKNOWN = 0` sentinel as proto3 requires 0-value)
-- `required/optional` qualifiers are dropped (proto3 has no required/optional)
-- Field numbers match thrift field IDs
-- `string` → `string`, `i32` → `int32`, `i64` → `int64`, `bool` → `bool`, 
`double` → `double`, `binary` → `bytes`
-- `list<T>` → `repeated T`
-- `map<K,V>` → `map<K,V>`
-- `set<T>` → `repeated T` (proto has no set; enforce uniqueness in application 
code)
-- Cross-file references: use `import` and fully qualified message names
-
-- [ ] **Step 1: Create directory**
-
-```bash
-mkdir -p airavata-api/src/main/proto/org/apache/airavata/model/workspace
-```
-
-- [ ] **Step 2: Write workspace.proto**
-
-```protobuf
-syntax = "proto3";
-
-package org.apache.airavata.model.workspace;
-
-option java_package = "org.apache.airavata.model.workspace";
-option java_outer_classname = "WorkspaceProtos";
-option java_multiple_files = true;
-
-import "org/apache/airavata/model/commons/commons.proto";
-
-message Group {
-    string group_name = 1;
-    string description = 2;
-}
-
-message Project {
-    string project_id = 1;
-    string owner = 2;
-    string gateway_id = 3;
-    string name = 4;
-    string description = 5;
-    int64 creation_time = 6;
-    repeated string shared_users = 7;
-    repeated string shared_groups = 8;
-}
-
-message User {
-    string airavata_internal_user_id = 1;
-    string user_name = 2;
-    string gateway_id = 3;
-    string first_name = 4;
-    string last_name = 5;
-    string email = 6;
-}
-
-enum GatewayApprovalStatus {
-    GATEWAY_APPROVAL_STATUS_UNKNOWN = 0;
-    REQUESTED = 1;
-    APPROVED = 2;
-    ACTIVE = 3;
-    DEACTIVATED = 4;
-    CANCELLED = 5;
-    DENIED = 6;
-    CREATED = 7;
-    DEPLOYED = 8;
-}
-
-message Gateway {
-    string airavata_internal_gateway_id = 1;
-    string gateway_id = 2;
-    GatewayApprovalStatus gateway_approval_status = 3;
-    string gateway_name = 4;
-    string domain = 5;
-    string email_address = 6;
-    string gateway_acronym = 7;
-    string gateway_url = 8;
-    string gateway_public_abstract = 9;
-    string review_proposal_description = 10;
-    string gateway_admin_first_name = 11;
-    string gateway_admin_last_name = 12;
-    string gateway_admin_email = 13;
-    string identity_server_user_name = 14;
-    string identity_server_password_token = 15;
-    string declined_reason = 16;
-    string oauth_client_id = 17;
-    string oauth_client_secret = 18;
-    int64 request_creation_time = 19;
-    string requester_username = 20;
-}
-
-message GatewayUsageReportingCommand {
-    string gateway_id = 1;
-    string compute_resource_id = 2;
-    string command = 3;
-}
-
-enum NotificationPriority {
-    NOTIFICATION_PRIORITY_UNKNOWN = 0;
-    LOW = 1;
-    NORMAL = 2;
-    HIGH = 3;
-}
-
-message Notification {
-    string notification_id = 1;
-    string gateway_id = 2;
-    string title = 3;
-    string notification_message = 4;
-    int64 creation_time = 5;
-    int64 published_time = 6;
-    int64 expiration_time = 7;
-    NotificationPriority priority = 8;
-}
-```
-
-- [ ] **Step 3: Commit**
-
-```bash
-git add airavata-api/src/main/proto/
-git commit -m "feat: add workspace proto definitions"
-```
-
----
-
-### Task 9: Create proto files — commons and security
-
-**Files:**
-- Create: 
`airavata-api/src/main/proto/org/apache/airavata/model/commons/commons.proto`
-- Create: 
`airavata-api/src/main/proto/org/apache/airavata/model/security/security.proto`
-
-These are foundational protos referenced by many others.
-
-- [ ] **Step 1: Create directories**
-
-```bash
-mkdir -p airavata-api/src/main/proto/org/apache/airavata/model/commons
-mkdir -p airavata-api/src/main/proto/org/apache/airavata/model/security
-```
-
-- [ ] **Step 2: Write commons.proto**
-
-Read 
`airavata-thrift-server/src/main/thrift/airavata-apis/airavata_commons.thrift` 
to get the exact constants and types. Translate to:
-
-```protobuf
-syntax = "proto3";
-
-package org.apache.airavata.model.commons;
-
-option java_package = "org.apache.airavata.model.commons";
-option java_outer_classname = "CommonsProtos";
-option java_multiple_files = true;
-
-// DEFAULT_ID is a compile-time constant in thrift; in proto it becomes a 
convention.
-// Consumers should use "DO_NOT_SET_AT_CLIENTS" as the default for ID fields.
-
-message ValidationResults {
-    bool validation_state = 1;
-    repeated ValidationResult validation_result_list = 2;
-}
-
-message ValidationResult {
-    bool result = 1;
-    string error_details = 2;
-}
-```
-
-- [ ] **Step 3: Write security.proto**
-
-Read 
`airavata-thrift-server/src/main/thrift/airavata-apis/security_model.thrift` 
and translate:
-
-```protobuf
-syntax = "proto3";
-
-package org.apache.airavata.model.security;
-
-option java_package = "org.apache.airavata.model.security";
-option java_outer_classname = "SecurityProtos";
-option java_multiple_files = true;
-
-message AuthzToken {
-    string access_token = 1;
-    map<string, string> claims_map = 2;
-}
-```
-
-- [ ] **Step 4: Commit**
-
-```bash
-git add airavata-api/src/main/proto/
-git commit -m "feat: add commons and security proto definitions"
-```
-
----
-
-### Task 10: Create proto files — status and experiment models
-
-**Files:**
-- Create: 
`airavata-api/src/main/proto/org/apache/airavata/model/status/status.proto`
-- Create: 
`airavata-api/src/main/proto/org/apache/airavata/model/experiment/experiment.proto`
-
-- [ ] **Step 1: Create directories**
-
-```bash
-mkdir -p airavata-api/src/main/proto/org/apache/airavata/model/status
-mkdir -p airavata-api/src/main/proto/org/apache/airavata/model/experiment
-```
-
-- [ ] **Step 2: Write status.proto**
-
-Read `airavata-thrift-server/src/main/thrift/data-models/status_models.thrift` 
and translate all enums/structs. Example structure:
-
-```protobuf
-syntax = "proto3";
-
-package org.apache.airavata.model.status;
-
-option java_package = "org.apache.airavata.model.status";
-option java_outer_classname = "StatusProtos";
-option java_multiple_files = true;
-
-enum ExperimentState {
-    EXPERIMENT_STATE_UNKNOWN = 0;
-    CREATED = 1;
-    VALIDATED = 2;
-    SCHEDULED = 3;
-    LAUNCHED = 4;
-    EXECUTING = 5;
-    CANCELING = 6;
-    CANCELED = 7;
-    COMPLETED = 8;
-    FAILED = 9;
-}
-
-message ExperimentStatus {
-    ExperimentState state = 1;
-    int64 time_of_state_change = 2;
-    string reason = 3;
-    int64 status_id = 4;
-}
-
-enum JobState {
-    JOB_STATE_UNKNOWN = 0;
-    SUBMITTED = 1;
-    QUEUED = 2;
-    ACTIVE = 3;
-    COMPLETE = 4;
-    CANCELED = 5;
-    FAILED = 6;
-    SUSPENDED = 7;
-    NON_CRITICAL_FAIL = 8;
-}
-
-message JobStatus {
-    JobState job_state = 1;
-    int64 time_of_state_change = 2;
-    string reason = 3;
-    int64 status_id = 4;
-}
-
-enum ProcessState {
-    PROCESS_STATE_UNKNOWN = 0;
-    CREATED = 1;
-    VALIDATED = 2;
-    STARTED = 3;
-    PRE_PROCESSING = 4;
-    CONFIGURING_WORKSPACE = 5;
-    INPUT_DATA_STAGING = 6;
-    EXECUTING = 7;
-    MONITORING = 8;
-    OUTPUT_DATA_STAGING = 9;
-    POST_PROCESSING = 10;
-    COMPLETED = 11;
-    FAILED = 12;
-    CANCELLING = 13;
-    CANCELED = 14;
-}
-
-message ProcessStatus {
-    ProcessState state = 1;
-    int64 time_of_state_change = 2;
-    string reason = 3;
-    int64 status_id = 4;
-}
-
-enum TaskState {
-    TASK_STATE_UNKNOWN = 0;
-    CREATED = 1;
-    EXECUTING = 2;
-    COMPLETED = 3;
-    FAILED = 4;
-    CANCELED = 5;
-}
-
-message TaskStatus {
-    TaskState state = 1;
-    int64 time_of_state_change = 2;
-    string reason = 3;
-    int64 status_id = 4;
-}
-
-message QueueStatusModel {
-    string host_name = 1;
-    string queue_name = 2;
-    bool queue_up = 3;
-    int32 running_jobs = 4;
-    int32 queued_jobs = 5;
-    int64 time = 6;
-}
-```
-
-- [ ] **Step 3: Write experiment.proto**
-
-Read 
`airavata-thrift-server/src/main/thrift/data-models/experiment_model.thrift` 
and translate. Use imports for cross-references:
-
-```protobuf
-syntax = "proto3";
-
-package org.apache.airavata.model.experiment;
-
-option java_package = "org.apache.airavata.model.experiment";
-option java_outer_classname = "ExperimentProtos";
-option java_multiple_files = true;
-
-import "org/apache/airavata/model/commons/commons.proto";
-import "org/apache/airavata/model/status/status.proto";
-// import other model protos as needed for cross-references
-
-enum ExperimentType {
-    EXPERIMENT_TYPE_UNKNOWN = 0;
-    SINGLE_APPLICATION = 1;
-    WORKFLOW = 2;
-}
-
-enum ExperimentSearchFields {
-    EXPERIMENT_SEARCH_FIELDS_UNKNOWN = 0;
-    EXPERIMENT_NAME = 1;
-    EXPERIMENT_DESC = 2;
-    APPLICATION_ID = 3;
-    FROM_DATE = 4;
-    TO_DATE = 5;
-    STATUS = 6;
-    PROJECT_ID = 7;
-    USER_NAME = 8;
-    JOB_ID = 9;
-}
-
-enum ProjectSearchFields {
-    PROJECT_SEARCH_FIELDS_UNKNOWN = 0;
-    PROJECT_NAME = 1;
-    PROJECT_DESCRIPTION = 2;
-}
-
-// Continue translating all structs from experiment_model.thrift:
-// UserConfigurationDataModel, ExperimentModel, ExperimentSummaryModel, 
ExperimentStatistics
-// Follow the same field-number and naming conventions as workspace.proto
-```
-
-- [ ] **Step 4: Commit**
-
-```bash
-git add airavata-api/src/main/proto/
-git commit -m "feat: add status and experiment proto definitions"
-```
-
----
-
-### Task 11: Create remaining proto files
-
-**Files:**
-- Create: one `.proto` file per thrift data-model file (approximately 25 more)
-
-This is mechanical translation work. For each thrift file in 
`airavata-thrift-server/src/main/thrift/data-models/`, create a corresponding 
proto file following the exact pattern from Tasks 8-10.
-
-- [ ] **Step 1: Create all remaining proto files**
-
-Complete checklist of thrift files to translate (check off each):
-
-| Thrift File | Proto Output Path |
-|-------------|------------------|
-| `account_provisioning_model.thrift` | 
`org/apache/airavata/model/appcatalog/accountprovisioning/account_provisioning.proto`
 |
-| `application_deployment_model.thrift` | 
`org/apache/airavata/model/appcatalog/appdeployment/app_deployment.proto` |
-| `application_interface_model.thrift` | 
`org/apache/airavata/model/appcatalog/appinterface/app_interface.proto` |
-| `application_io_models.thrift` | 
`org/apache/airavata/model/application/io/application_io.proto` |
-| `compute_resource_model.thrift` | 
`org/apache/airavata/model/appcatalog/computeresource/compute_resource.proto` |
-| `credential_store_models.thrift` | 
`org/apache/airavata/model/credential/store/credential_store.proto` |
-| `data_movement_models.thrift` | 
`org/apache/airavata/model/data/movement/data_movement.proto` |
-| `gateway_groups_model.thrift` | 
`org/apache/airavata/model/appcatalog/gatewaygroups/gateway_groups.proto` |
-| `gateway_resource_profile_model.thrift` | 
`org/apache/airavata/model/appcatalog/gatewayprofile/gateway_profile.proto` |
-| `group_manager_model.thrift` | 
`org/apache/airavata/model/group/group_manager.proto` |
-| `group_resource_profile_model.thrift` | 
`org/apache/airavata/model/appcatalog/groupresourceprofile/group_resource_profile.proto`
 |
-| `job_model.thrift` | `org/apache/airavata/model/job/job.proto` |
-| `parallelism_model.thrift` | 
`org/apache/airavata/model/parallelism/parallelism.proto` |
-| `parser_model.thrift` | 
`org/apache/airavata/model/appcatalog/parser/parser.proto` |
-| `process_model.thrift` | `org/apache/airavata/model/process/process.proto` |
-| `replica_catalog_models.thrift` | 
`org/apache/airavata/model/data/replica/replica_catalog.proto` |
-| `scheduling_model.thrift` | 
`org/apache/airavata/model/scheduling/scheduling.proto` |
-| `sharing_models.thrift` | `org/apache/airavata/model/sharing/sharing.proto` |
-| `storage_resource_model.thrift` | 
`org/apache/airavata/model/appcatalog/storageresource/storage_resource.proto` |
-| `task_model.thrift` | `org/apache/airavata/model/task/task.proto` |
-| `tenant_profile_model.thrift` | 
`org/apache/airavata/model/tenant/tenant_profile.proto` |
-| `user_profile_model.thrift` | 
`org/apache/airavata/model/user/user_profile.proto` |
-| `user_resource_profile_model.thrift` | 
`org/apache/airavata/model/appcatalog/userresourceprofile/user_resource_profile.proto`
 |
-| `workflow_data_model.thrift` | 
`org/apache/airavata/model/workflow/data/workflow_data.proto` |
-| `workflow_model.thrift` | 
`org/apache/airavata/model/workflow/workflow.proto` |
-
-Also translate API-level thrift files:
-
-| Thrift File | Proto Output Path |
-|-------------|------------------|
-| `airavata_errors.thrift` | `org/apache/airavata/model/error/errors.proto` |
-| `db_event_model.thrift` | `org/apache/airavata/model/dbevent/db_event.proto` 
|
-| `messaging_events.thrift` | 
`org/apache/airavata/model/messaging/messaging_events.proto` |
-
-For each file:
-1. Read the thrift file
-2. Create the proto file following translation rules from Task 8
-3. Match field numbers to thrift field IDs
-4. Add `UNKNOWN = 0` sentinel to every enum
-5. Use `import` for cross-file references
-6. Set `java_package` matching the thrift `namespace java`
-
-- [ ] **Step 2: Commit**
-
-```bash
-git add airavata-api/src/main/proto/
-git commit -m "feat: add all remaining proto definitions mirroring thrift IDL"
-```
-
----
-
-### Task 12: Set up protoc compilation in airavata-api
-
-**Files:**
-- Modify: `airavata-api/pom.xml`
-
-- [ ] **Step 1: Add protobuf-java dependency**
-
-In `airavata-api/pom.xml` `<dependencies>` section, add:
-
-```xml
-    <dependency>
-      <groupId>com.google.protobuf</groupId>
-      <artifactId>protobuf-java</artifactId>
-    </dependency>
-```
-
-- [ ] **Step 2: Add protobuf-maven-plugin**
-
-In `airavata-api/pom.xml` `<build><plugins>` section, add the 
protobuf-maven-plugin (already in root POM's pluginManagement):
-
-```xml
-      <plugin>
-        <groupId>io.github.ascopes</groupId>
-        <artifactId>protobuf-maven-plugin</artifactId>
-        <executions>
-          <execution>
-            <id>generate-proto-sources</id>
-            <goals>
-              <goal>generate</goal>
-            </goals>
-            <configuration>
-              <sourceDirectories>
-                
<sourceDirectory>${project.basedir}/src/main/proto</sourceDirectory>
-              </sourceDirectories>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-```
-
-- [ ] **Step 3: Verify proto compilation**
-
-```bash
-mvn generate-sources -pl airavata-api --quiet 2>&1 | tail -10
-ls 
airavata-api/target/generated-sources/protobuf/java/org/apache/airavata/model/workspace/
-```
-
-Expected: generated Java files for the proto messages (Project.java, 
Gateway.java, etc.)
-
-- [ ] **Step 4: Full compile**
-
-```bash
-mvn compile -pl airavata-api --quiet 2>&1 | tail -5
-```
-
-Expected: BUILD SUCCESS — both thrift generated code and proto generated code 
compile.
-
-- [ ] **Step 5: Commit**
-
-```bash
-git add airavata-api/pom.xml
-git commit -m "build: add protobuf-java dependency and protoc compilation to 
airavata-api"
-```
-
----
-
-### Task 13: Add MapStruct to airavata-thrift-server
-
-**Files:**
-- Modify: `airavata-thrift-server/pom.xml`
-- Modify: `pom.xml` (root — add MapStruct to dependency management)
-
-- [ ] **Step 1: Add MapStruct to root pom.xml dependency management**
-
-In `pom.xml` root, add to `<dependencyManagement><dependencies>`:
-
-```xml
-            <dependency>
-                <groupId>org.mapstruct</groupId>
-                <artifactId>mapstruct</artifactId>
-                <version>1.6.3</version>
-            </dependency>
-            <dependency>
-                <groupId>org.mapstruct</groupId>
-                <artifactId>mapstruct-processor</artifactId>
-                <version>1.6.3</version>
-            </dependency>
-```
-
-- [ ] **Step 2: Add MapStruct dependency to airavata-thrift-server/pom.xml**
-
-Add to `<dependencies>`:
-
-```xml
-    <dependency>
-      <groupId>org.mapstruct</groupId>
-      <artifactId>mapstruct</artifactId>
-    </dependency>
-```
-
-Add to `<build><plugins>`:
-
-```xml
-    <build>
-      <plugins>
-        <plugin>
-          <groupId>org.apache.maven.plugins</groupId>
-          <artifactId>maven-compiler-plugin</artifactId>
-          <configuration>
-            <annotationProcessorPaths>
-              <path>
-                <groupId>org.mapstruct</groupId>
-                <artifactId>mapstruct-processor</artifactId>
-                <version>1.6.3</version>
-              </path>
-            </annotationProcessorPaths>
-          </configuration>
-        </plugin>
-      </plugins>
-    </build>
-```
-
-- [ ] **Step 3: Verify build**
-
-```bash
-mvn compile -pl airavata-thrift-server -am --quiet 2>&1 | tail -5
-```
-
-Expected: BUILD SUCCESS
-
-- [ ] **Step 4: Commit**
-
-```bash
-git add pom.xml airavata-thrift-server/pom.xml
-git commit -m "build: add MapStruct dependency to airavata-thrift-server"
-```
-
----
-
-### Task 14: Create representative MapStruct mapper
-
-**Files:**
-- Create: 
`airavata-thrift-server/src/main/java/org/apache/airavata/api/server/mapper/WorkspaceMapper.java`
-
-This establishes the mapper pattern. Full mapper coverage is built 
incrementally as services are converted to proto types (follow-up work).
-
-- [ ] **Step 1: Create mapper directory**
-
-```bash
-mkdir -p 
airavata-thrift-server/src/main/java/org/apache/airavata/api/server/mapper
-```
-
-- [ ] **Step 2: Write WorkspaceMapper.java**
-
-```java
-package org.apache.airavata.api.server.mapper;
-
-import org.apache.airavata.model.workspace.Gateway;
-import org.apache.airavata.model.workspace.Notification;
-import org.apache.airavata.model.workspace.Project;
-import org.mapstruct.Mapper;
-import org.mapstruct.Mapping;
-import org.mapstruct.factory.Mappers;
-
-/**
- * Maps between thrift-generated workspace types and proto-generated workspace 
types.
- *
- * <p>Thrift types use camelCase field accessors (getGatewayId()).
- * Proto types use snake_case with standard proto getters (getGatewayId()).
- * MapStruct handles the mapping automatically when accessor names match.
- */
-@Mapper
-public interface WorkspaceMapper {
-    WorkspaceMapper INSTANCE = Mappers.getMapper(WorkspaceMapper.class);
-
-    // --- Project ---
-    org.apache.airavata.model.workspace.ProjectProtos.Project toProto(Project 
thrift);
-    Project toThrift(org.apache.airavata.model.workspace.ProjectProtos.Project 
proto);
-
-    // --- Gateway ---
-    org.apache.airavata.model.workspace.WorkspaceProtos.Gateway 
toProtoGateway(Gateway thrift);
-    Gateway 
toThriftGateway(org.apache.airavata.model.workspace.WorkspaceProtos.Gateway 
proto);
-}
-```
-
-Note: The exact proto class names depend on how protoc generates them (based 
on `java_multiple_files`, `java_outer_classname`). Adjust class references 
after verifying proto compilation output from Task 12.
-
-- [ ] **Step 3: Verify compilation**
-
-```bash
-mvn compile -pl airavata-thrift-server -am --quiet 2>&1 | tail -10
-```
-
-If proto class names don't match, check 
`airavata-api/target/generated-sources/` for exact class names and update 
mapper imports.
-
-- [ ] **Step 4: Commit**
-
-```bash
-git add 
airavata-thrift-server/src/main/java/org/apache/airavata/api/server/mapper/
-git commit -m "feat: add representative MapStruct mapper for workspace types"
-```
-
----
-
-### Task 15: Final build verification and cleanup
-
-**Files:**
-- None (verification only)
-
-- [ ] **Step 1: Full project build**
-
-```bash
-mvn clean compile -T4 2>&1 | tail -20
-```
-
-Expected: BUILD SUCCESS for all modules
-
-- [ ] **Step 2: Run tests**
-
-```bash
-mvn test -pl airavata-api,airavata-thrift-server 2>&1 | tail -20
-```
-
-Expected: All tests pass
-
-- [ ] **Step 3: Verify no remaining handler references in airavata-api**
-
-```bash
-grep -r "AiravataServer\b" airavata-api/src/main/java/ --include="*.java" | 
grep -v "import"
-grep -r "AiravataServerHandler\b" airavata-api/src/main/java/ 
--include="*.java" | grep -v "import"
-```
-
-Expected: No matches (these classes have moved). If there are stale 
references, remove them.
-
-- [ ] **Step 4: Commit**
-
-```bash
-git add -A
-git commit -m "chore: final cleanup after thrift server extraction"
-```
-
----
-
-## Deferred Work (Future Plans)
-
-These items are explicitly out of scope for this plan but are required for 
full thrift removal from `airavata-api`:
-
-1. **Extract data access from Registry/Sharing/Credential handlers** — Create 
non-thrift interfaces in `airavata-api`, refactor services to use them, move 
handler implementations to `airavata-thrift-server`
-2. **Convert service signatures to proto types** — Change all 14 service 
classes to accept/return proto types instead of thrift types
-3. **Move thrift code generation to airavata-thrift-server** — Once 
`airavata-api` no longer imports any thrift types
-4. **Remove libthrift dependency from airavata-api** — Final step after all 
thrift references are eliminated
-5. **Full MapStruct mapper coverage** — One mapper per domain (experiment, 
credential, sharing, etc.)
diff --git 
a/docs/superpowers/specs/2026-03-26-airavata-thrift-server-extraction-design.md 
b/docs/superpowers/specs/2026-03-26-airavata-thrift-server-extraction-design.md
deleted file mode 100644
index c792b0596e..0000000000
--- 
a/docs/superpowers/specs/2026-03-26-airavata-thrift-server-extraction-design.md
+++ /dev/null
@@ -1,190 +0,0 @@
-# Airavata Thrift Server Extraction Design
-
-**Date:** 2026-03-26
-**Status:** Draft
-
-## Goal
-
-Extract all thrift server concerns from `airavata-api` into a new 
`airavata-thrift-server` Maven module. Introduce protobuf DTOs as the canonical 
data types in the service layer, making `airavata-api` completely thrift-free. 
MapStruct mappers in `airavata-thrift-server` bridge proto and thrift types at 
the handler boundary.
-
-## Repository Layout (Post-Extraction)
-
-```
-airavata/
-├── airavata-thrift-server/             # NEW — all thrift concerns
-│   ├── pom.xml
-│   └── src/main/
-│       ├── java/
-│       │   └── org/apache/airavata/
-│       │       ├── server/             # AiravataServer.java 
(TMultiplexedProcessor bootstrap)
-│       │       ├── handler/            # All 9 thrift handlers
-│       │       └── mapper/             # MapStruct mappers (proto <-> thrift)
-│       └── thrift/                     # Moved from 
thrift-interface-descriptions/
-│           ├── airavata-apis/
-│           ├── base-api/
-│           ├── data-models/
-│           ├── service-cpis/
-│           └── stubs_java.thrift (etc.)
-│
-├── airavata-api/                       # SLIMMED — services + background 
processes
-│   ├── pom.xml
-│   └── src/main/
-│       ├── java/
-│       │   └── org/apache/airavata/
-│       │       ├── service/            # Business logic services
-│       │       ├── repository/         # JPA data access
-│       │       └── background/         # Helix, monitors, event managers, etc.
-│       └── proto/                      # NEW — .proto files mirroring thrift 
IDL
-│           └── org/apache/airavata/
-│               ├── model/
-│               ├── api/
-│               ├── registry/
-│               ├── credential/
-│               ├── sharing/
-│               └── ...
-│
-├── modules/                            # Unchanged
-└── pom.xml                             # Root — adds airavata-thrift-server 
module
-```
-
-## Dependency Graph
-
-```
-airavata-thrift-server
-├── depends on: airavata-api (service layer + proto generated classes)
-├── depends on: libthrift (Apache Thrift runtime)
-├── owns: thrift IDL compilation -> generated thrift Java classes
-├── owns: MapStruct mappers (proto <-> thrift)
-└── owns: TMultiplexedProcessor, TThreadPoolServer bootstrap
-
-airavata-api
-├── depends on: protobuf-java (for generated proto classes)
-├── owns: service layer (o.a.a.service.*)
-├── owns: repository / data access layer
-├── owns: background services (Helix, monitors, event managers)
-├── owns: proto definitions + protoc generation
-└── NO thrift dependency
-```
-
-## Thrift Services Moved (All 9)
-
-| Service Name        | Handler Class                      |
-|---------------------|------------------------------------|
-| Airavata            | AiravataServerHandler              |
-| RegistryService     | RegistryServerHandler              |
-| SharingRegistry     | SharingRegistryServerHandler       |
-| CredentialStore     | CredentialStoreServerHandler       |
-| UserProfile         | UserProfileServiceHandler          |
-| TenantProfile       | TenantProfileServiceHandler        |
-| IamAdminServices    | IamAdminServicesHandler            |
-| GroupManager        | GroupManagerServiceHandler          |
-| Orchestrator        | OrchestratorServerHandler          |
-
-## What Stays in `airavata-api`
-
-### Services (refactored to proto types)
-All 14 business logic services: ExperimentService, ApplicationCatalogService, 
CredentialService, GatewayService, GatewayResourceProfileService, 
GroupResourceProfileService, NotificationService, ParserService, 
ProjectService, ResourceService, UserResourceProfileService, 
DataProductService, ResourceSharingService, SSHAccountService.
-
-### Data Access
-JPA entities, repositories, Hibernate config, database initialization 
(ExpCatalogDB, AppCatalogDB, ReplicaCatalogDB, WorkflowCatalogDB, 
CredentialStoreDB, UserProfileCatalogDB).
-
-### Background Services (retains its own main entry point)
-- DB Event Manager
-- Monitoring Server (Prometheus on port 9097)
-- Cluster Status Monitor
-- Data Interpreter
-- Process Rescheduler
-- Helix Controller/Participant
-- Workflow Managers (Pre/Post/Parser)
-- Job Monitors (Email + Real-time)
-
-### Removed from `airavata-api`
-- `AiravataServer.java`
-- All 9 thrift handler classes
-- Thrift IDL files
-- `libthrift` dependency
-- Thrift code generation Maven plugin config
-
-## Proto File Strategy
-
-Proto files mirror thrift IDL 1:1 — same fields, same nesting, same enums. 
Mechanical translation, not a redesign.
-
-### Conventions
-- Field numbers match thrift field IDs where possible
-- Proto uses `snake_case` per protobuf convention; MapStruct handles naming 
differences
-- No proto service definitions — only message types (no gRPC yet)
-- Package structure mirrors thrift: `org.apache.airavata.model.*`, 
`org.apache.airavata.api.*`, etc.
-- Generated via protoc Maven plugin in `airavata-api`
-
-### Example
-
-Thrift:
-```thrift
-struct ExperimentModel {
-    1: string experimentId,
-    2: string projectId,
-    3: string gatewayId,
-    4: ExperimentType experimentType,
-    5: string userName,
-    6: string experimentName,
-    7: i64 creationTime
-}
-```
-
-Proto:
-```protobuf
-message ExperimentModel {
-    string experiment_id = 1;
-    string project_id = 2;
-    string gateway_id = 3;
-    ExperimentType experiment_type = 4;
-    string user_name = 5;
-    string experiment_name = 6;
-    int64 creation_time = 7;
-}
-```
-
-## Handler Conversion Pattern
-
-```
-Thrift Client
-  -> TMultiplexedProcessor (airavata-thrift-server)
-    -> ThriftHandler.method(ThriftRequest)
-      -> MapStruct: ThriftRequest -> ProtoDTO
-        -> Service.method(ProtoDTO)          (airavata-api)
-        -> returns ProtoResult
-      -> MapStruct: ProtoResult -> ThriftResponse
-    -> returns ThriftResponse
-```
-
-### Example — createExperiment
-
-```java
-// In airavata-thrift-server: AiravataServerHandler
-public String createExperiment(AuthzToken authzToken, String gatewayId, 
ExperimentModel experiment) {
-    var protoExperiment = ExperimentMapper.INSTANCE.toProto(experiment);
-    var protoAuthz = AuthzTokenMapper.INSTANCE.toProto(authzToken);
-    var result = experimentService.createExperiment(protoAuthz, gatewayId, 
protoExperiment);
-    return result;
-}
-```
-
-### MapStruct Mapper
-
-```java
-@Mapper
-public interface ExperimentMapper {
-    ExperimentMapper INSTANCE = Mappers.getMapper(ExperimentMapper.class);
-    ExperimentProto toProto(ExperimentModel thriftModel);
-    ExperimentModel toThrift(ExperimentProto proto);
-}
-```
-
-## Build Order
-
-1. `airavata-api` builds first — compiles proto files, produces service 
classes + proto generated code
-2. `airavata-thrift-server` builds second — compiles thrift IDL, compiles 
handlers + mappers against airavata-api
-
-## Development
-
-Work is done in a git worktree off the main `airavata` repo for isolation. 
Thrift IDL content is unchanged (no SDK breakage). Thrift spec changes are a 
separate future effort.
diff --git 
a/integration-tests/src/test/java/org/apache/airavata/integration/BackgroundServiceHealthTest.java
 
b/integration-tests/src/test/java/org/apache/airavata/integration/BackgroundServiceHealthTest.java
index 14d0aff42d..677f53e8eb 100644
--- 
a/integration-tests/src/test/java/org/apache/airavata/integration/BackgroundServiceHealthTest.java
+++ 
b/integration-tests/src/test/java/org/apache/airavata/integration/BackgroundServiceHealthTest.java
@@ -73,7 +73,9 @@ class BackgroundServiceHealthTest {
         HttpResponse<String> response = httpClient.send(request, 
HttpResponse.BodyHandlers.ofString());
         assertEquals(200, response.statusCode(),
                 "Could not reach /health/services — got HTTP " + 
response.statusCode());
-        cachedRoot = objectMapper.readTree(response.body());
+        JsonNode body = objectMapper.readTree(response.body());
+        cachedRoot = body.get("services");
+        assertNotNull(cachedRoot, "Expected 'services' key in /health/services 
response");
     }
 
     static Stream<String> expectedServices() {
diff --git 
a/integration-tests/src/test/java/org/apache/airavata/integration/ServiceHealthEndpointTest.java
 
b/integration-tests/src/test/java/org/apache/airavata/integration/ServiceHealthEndpointTest.java
index 219ff00d35..b9b12048e9 100644
--- 
a/integration-tests/src/test/java/org/apache/airavata/integration/ServiceHealthEndpointTest.java
+++ 
b/integration-tests/src/test/java/org/apache/airavata/integration/ServiceHealthEndpointTest.java
@@ -82,7 +82,9 @@ class ServiceHealthEndpointTest {
         JsonNode root = objectMapper.readTree(response.body());
         assertNotNull(root, "Response body could not be parsed as JSON");
         assertTrue(root.isObject(), "Expected JSON object at root, got: " + 
root.getNodeType());
-        assertFalse(root.isEmpty(), "Expected at least one service entry in 
the response");
+        JsonNode services = root.get("services");
+        assertNotNull(services, "Expected 'services' key in response, got: " + 
root);
+        assertFalse(services.isEmpty(), "Expected at least one service entry 
in the response");
     }
 
     @Test
@@ -91,7 +93,9 @@ class ServiceHealthEndpointTest {
         assertEquals(200, response.statusCode());
 
         JsonNode root = objectMapper.readTree(response.body());
-        Iterator<Map.Entry<String, JsonNode>> fields = root.fields();
+        JsonNode services = root.get("services");
+        assertNotNull(services, "Expected 'services' key in response");
+        Iterator<Map.Entry<String, JsonNode>> fields = services.fields();
         while (fields.hasNext()) {
             Map.Entry<String, JsonNode> entry = fields.next();
             String serviceName = entry.getKey();

Reply via email to