# Deploy Artifacts to Sites — Remove Config DB Dependency > **For Claude:** REQUIRED SUB-SKILL: Use superpowers-extended-cc:executing-plans to implement this plan task-by-task. **Goal:** Make site servers fully self-contained by reading external system, notification, and data connection configs from local SQLite instead of the central config DB. **Architecture:** The artifact deployment pipeline already exists (`DeployArtifactsCommand` → `DeploymentManagerActor` → `SiteStorageService`). The gap is that runtime services still query the config DB. We create site-local repository implementations backed by SQLite, wire them into DI, add a UI button to trigger deployment, and extend artifacts to include data connections. **Tech Stack:** C#, SQLite (Microsoft.Data.Sqlite), Blazor Server, Akka.NET messaging --- ### Task 1: Create SiteExternalSystemRepository **Files:** - Create: `src/ScadaLink.SiteRuntime/Repositories/SiteExternalSystemRepository.cs` **Step 1:** Create `SiteExternalSystemRepository` implementing `IExternalSystemRepository`. Read-only methods query `SiteStorageService` SQLite tables. Write methods throw `NotSupportedException` (site is read-only for these configs). ```csharp // Key methods to implement: // GetAllExternalSystemsAsync → query external_systems table, deserialize method_definitions JSON // GetMethodsByExternalSystemIdAsync → parse method_definitions from external_systems row // GetAllDatabaseConnectionsAsync → query database_connections table // All Add/Update/Delete methods → throw NotSupportedException("Managed via artifact deployment") ``` The `external_systems` table stores `method_definitions` as JSON. Parse it into `List` on read. The `ExternalSystemDefinition` entity needs Id, Name, EndpointUrl, AuthType, AuthConfiguration. Map the `name` column to a synthetic Id (hash or sequential). **Step 2:** Build and verify no compile errors. **Step 3:** Commit: `feat: add SiteExternalSystemRepository backed by SQLite` --- ### Task 2: Create SiteNotificationRepository **Files:** - Create: `src/ScadaLink.SiteRuntime/Repositories/SiteNotificationRepository.cs` **Step 1:** Create `SiteNotificationRepository` implementing `INotificationRepository`. Read-only methods query `SiteStorageService` SQLite tables. ```csharp // Key methods: // GetListByNameAsync → query notification_lists by name // GetRecipientsByListIdAsync → parse recipient_emails JSON from notification_lists row // GetAllSmtpConfigurationsAsync → needs new smtp_configurations SQLite table // All Add/Update/Delete → throw NotSupportedException ``` **Step 2:** Add `smtp_configurations` table to `SiteStorageService.InitializeAsync()`: ```sql CREATE TABLE IF NOT EXISTS smtp_configurations ( name TEXT PRIMARY KEY, server TEXT NOT NULL, port INTEGER NOT NULL, auth_mode TEXT NOT NULL, from_address TEXT NOT NULL, username TEXT, password TEXT, oauth_config TEXT, updated_at TEXT NOT NULL ); ``` **Step 3:** Add `StoreSmtpConfigurationAsync` method to `SiteStorageService`. **Step 4:** Build and verify. **Step 5:** Commit: `feat: add SiteNotificationRepository and SMTP storage` --- ### Task 3: Add data connections to DeployArtifactsCommand **Files:** - Modify: `src/ScadaLink.Commons/Messages/Artifacts/DeployArtifactsCommand.cs` - Modify: `src/ScadaLink.SiteRuntime/Actors/DeploymentManagerActor.cs` (HandleDeployArtifacts) - Modify: `src/ScadaLink.SiteRuntime/Persistence/SiteStorageService.cs` **Step 1:** Add `DataConnectionArtifact` record and include it in `DeployArtifactsCommand`: ```csharp public record DataConnectionArtifact( string Name, string Protocol, string? ConfigurationJson); // Add to DeployArtifactsCommand: IReadOnlyList? DataConnections ``` **Step 2:** Add `data_connection_definitions` table to `SiteStorageService.InitializeAsync()`: ```sql CREATE TABLE IF NOT EXISTS data_connection_definitions ( name TEXT PRIMARY KEY, protocol TEXT NOT NULL, configuration TEXT, updated_at TEXT NOT NULL ); ``` **Step 3:** Add `StoreDataConnectionDefinitionAsync` and `GetAllDataConnectionDefinitionsAsync` to `SiteStorageService`. **Step 4:** Update `DeploymentManagerActor.HandleDeployArtifacts` to persist data connections. **Step 5:** Update `HandleDeployArtifacts` SMTP config storage (add to the existing handler alongside external systems and db connections). **Step 6:** Build and verify. **Step 7:** Commit: `feat: include data connections and SMTP in artifact deployment` --- ### Task 4: Wire site-local repositories into DI **Files:** - Modify: `src/ScadaLink.Host/Program.cs` (Site role, lines ~155-160) - Modify: `src/ScadaLink.Host/appsettings.Site.json` - Modify: `src/ScadaLink.SiteRuntime/ServiceCollectionExtensions.cs` **Step 1:** In `ServiceCollectionExtensions.AddSiteRuntime()`, register the site-local repositories: ```csharp services.AddScoped(); services.AddScoped(); ``` **Step 2:** Remove `AddConfigurationDatabase` call from the Site role in `Program.cs`. Remove the `ConfigurationDb` connection string check. **Step 3:** Remove `ConfigurationDb` from `appsettings.Site.json`. **Step 4:** Build and verify — site should start without SQL Server. **Step 5:** Commit: `feat: wire site-local repos, remove config DB dependency from Site` --- ### Task 5: Add Deploy Artifacts button to Sites admin page **Files:** - Modify: `src/ScadaLink.CentralUI/Components/Pages/Admin/Sites.razor` **Step 1:** Inject `ArtifactDeploymentService` and add a "Deploy Artifacts" button in each site's action column (next to Edit/Delete). **Step 2:** Add handler method that: - Collects all external systems, db connections, notification lists, SMTP configs, shared scripts, and data connections from config DB repositories - Builds a `DeployArtifactsCommand` - Calls `ArtifactDeploymentService.DeployToAllSitesAsync` (or per-site variant) - Shows success/failure toast **Step 3:** Add a "Deploy Artifacts to All Sites" button in the page header for bulk deployment. **Step 4:** Build and verify UI renders. **Step 5:** Commit: `feat: add Deploy Artifacts button to Sites admin page` --- ### Task 6: Update ArtifactDeploymentService to include all artifact types **Files:** - Modify: `src/ScadaLink.DeploymentManager/ArtifactDeploymentService.cs` **Step 1:** Inject `ISiteRepository` (for data connections) and `INotificationRepository` (for SMTP configs). Update the command-building logic to include: - Data connections from `ISiteRepository.GetAllDataConnectionsAsync()` - SMTP configurations from `INotificationRepository.GetAllSmtpConfigurationsAsync()` **Step 2:** Build and verify. **Step 3:** Commit: `feat: include data connections and SMTP in artifact collection` --- ### Task 7: End-to-end test **Step 1:** Start Central and Site servers. **Step 2:** Login as admin, navigate to Sites page, click "Deploy Artifacts" on Test Plant A. **Step 3:** Verify site logs show artifact receipt and SQLite storage. **Step 4:** Restart Site without config DB connection string — verify it starts and ExternalSystemClient/NotificationDeliveryService work from local data. **Step 5:** Commit any fixes.