# Service Center Migration Plan ## Overview This document describes a **step-by-step plan** to migrate from the old `modules/services` (Services hub) to the new `modules/serviceCenter`. The migration is **incremental**—one feature at a time—with UI-driven testing after each step. **Recommended first feature: Chatbot** — it has a clear UI, limited service dependencies, and is already partially using the service center (AI, generation, billing). --- ## Architecture Summary ### Current State | Component | Location | Notes | |-----------|----------|-------| | **Service Center** | `modules/serviceCenter/` | New: registry, resolver, context-based DI | | **Services Hub** | `modules/services/` | Legacy: `getInterface()` → `Services` instance | | **Chatbot** | `modules/features/chatbot/` | Uses `getServices()` → `.chat`, `.ai` | ### Service Center vs Legacy Services | Aspect | Service Center | Legacy Services | |--------|----------------|-----------------| | **Constructor** | `(context: ServiceCenterContext, get_service)` | `(services: Services)` — receives hub | | **Context** | Minimal: user, mandate_id, feature_instance_id, workflow | Full hub with all interfaces | | **Dependencies** | Injected via `get_service("key")` | Via `self.services.` | | **RBAC** | Per-service `objectKey` in registry | Shared via hub | | **Pre-warm** | `preWarm()` at app startup | Loaded on first use | ### Services Already Using Service Center (in Services class) The `Services` class in `modules/services/__init__.py` already uses `getService()` for: - `messaging` - `ai` - `generation` - `billing` ### Services Still Using Legacy Direct Imports - `chat` ← **Target for Phase 1** - `sharepoint` - `ticket` - `utils` - `security` - `streaming` - `extraction` - `web` --- ## Phase 1: Migrate Chatbot to Use Service Center for Chat **Goal:** Switch the Chatbot feature to get the Chat service from Service Center instead of the legacy hub. This validates the full flow with minimal risk. ### Step 1.1: Switch Services Class to Use Service Center for Chat **File:** `modules/services/__init__.py` **Change:** Replace the direct ChatService import with `getService("chat", ...)`. ```python # BEFORE (line ~126-127): from .serviceChat.mainServiceChat import ChatService self.chat = PublicService(ChatService(self)) # AFTER: self.chat = PublicService(getService("chat", _ctx, legacy_hub=self)) ``` The `_ctx` (ServiceCenterContext) is already created for messaging/ai/generation. Add `workflow=self.workflow` to the context if not already present (it should be—check the existing `_ctx` creation around line 109–116). **Verification:** 1. Ensure `ServiceCenterContext` includes `workflow` when Services has one (chatbot often passes `workflow=None` initially). 2. The service center ChatService gets `interfaceDbComponent` from `getInterface(context.user, mandateId=context.mandate_id)` — same as legacy. The chatbot calls `getFileInfo(fileId)` which only needs `interfaceDbComponent`, not workflow. ### Step 1.2: Ensure Service Center Context Has Workflow **File:** `modules/services/__init__.py` Verify the existing context creation: ```python _ctx = ServiceCenterContext( user=self.user, mandate_id=self.mandateId, feature_instance_id=self.featureInstanceId, workflow=self.workflow, ) ``` If `workflow` is missing, add it. The ChatService uses `_context.workflow` for methods like `getChatDocumentsFromDocumentList`; for `getFileInfo` it is not needed. ### Step 1.3: Run Unit Tests ```powershell cd c:\Users\IdaDittrich\Documents\01_Code\gateway pytest tests/unit/serviceCenter/test_service_center_imports.py -v python tests/scripts/smoke_test_service_center.py ``` ### Step 1.4: Manual UI Test — Chatbot with File Upload 1. **Start the gateway:** ```powershell cd c:\Users\IdaDittrich\Documents\01_Code\gateway uvicorn app:app --reload --host 0.0.0.0 --port 8000 ``` 2. **Start the frontend** (if using frontend_nyla): ```powershell cd c:\Users\IdaDittrich\Documents\01_Code\frontend_nyla npm run dev ``` 3. **Log in** as a user with access to the Chatbot feature. 4. **Open a Chatbot instance** (navigate to the chatbot feature, select or create an instance). 5. **Create a new conversation** — click "New conversation" or equivalent. 6. **Attach a file** — upload a PDF or document before sending. 7. **Send a message** — e.g. "Summarize this document." 8. **Verify:** - No 500 errors in gateway logs - File is processed (chat service’s `getFileInfo` is used when creating `ChatbotDocument`s) - AI response streams back correctly (AI service already from service center) ### Step 1.5: Rollback if Needed If something breaks, revert the change in `modules/services/__init__.py`: ```python from .serviceChat.mainServiceChat import ChatService self.chat = PublicService(ChatService(self)) ``` --- ## Phase 2 (Future): Migrate Extraction for Chatbot The chatbot may use extraction when processing documents. After Phase 1 is stable: 1. Switch `Services` to use `getService("extraction", _ctx, legacy_hub=self)` instead of direct import. 2. Ensure `ExtractionService` in service center has the same interface as the legacy one. 3. Re-test chatbot with document-heavy prompts. --- ## Phase 3 (Future): Migrate Remaining Services | Service | Used By | Priority | |---------|---------|----------| | utils | Chat, Extraction, AI, Web, Generation | High (core) | | security | Sharepoint | Medium | | streaming | Workflows, Chatbot SSE | Medium | | sharepoint | Sharepoint workflows | Medium | | ticket | Ticket system | Low | | web | Web research workflows | Medium | --- ## Service Center Bootstrap (Already Done) The app already: - Calls `preWarm()` at startup (`app.py` lifespan) - Has `registerServiceObjects()` available for RBAC catalog (call from bootstrap if needed) ### Optional: Register Service RBAC Objects If you want service-level RBAC (e.g. `can_access_service()`), call during bootstrap: ```python # In app.py lifespan or interfaceBootstrap from modules.serviceCenter import registerServiceObjects from modules.security.rbacCatalog import getCatalogService catalogService = getCatalogService() registerServiceObjects(catalogService) ``` --- ## Testing Checklist (Chatbot Phase 1) - [ ] Unit tests pass: `pytest tests/unit/serviceCenter/ -v` - [ ] Smoke test passes: `python tests/scripts/smoke_test_service_center.py` - [ ] Gateway starts without import errors - [ ] Chatbot UI loads - [ ] New conversation creates successfully - [ ] Message without file sends and gets AI response - [ ] Message with file attachment sends and gets AI response - [ ] No errors in gateway logs during the above flows --- ## File Summary for Phase 1 | File | Action | |------|--------| | `modules/services/__init__.py` | Replace `ChatService` import with `getService("chat", _ctx, legacy_hub=self)` | | (No other changes) | Service center ChatService and resolver already support legacy fallback | --- ## FAQ **Q: Why start with Chat instead of Utils?** A: Chat has a clear UI path (chatbot) and only a few call sites. Utils is used everywhere; migrating it later reduces risk. **Q: What if `getService("chat", ctx)` fails?** A: The resolver passes `legacy_hub=self`, so it falls back to the legacy `Services.chat` if the service center module fails to load. You get graceful degradation. **Q: Can I test without the frontend?** A: Yes. Use the API directly, e.g. `POST /api/chatbot/{instanceId}/start/stream` with a valid `UserInputRequest` (with `listFileId` for file upload).