docs: add architecture review spec and implementation plans
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
377
docs/superpowers/plans/2026-04-07-plan4-saas-cleanup.md
Normal file
377
docs/superpowers/plans/2026-04-07-plan4-saas-cleanup.md
Normal file
@@ -0,0 +1,377 @@
|
||||
# Plan 4: SaaS Cleanup — Strip to Vendor Management Plane
|
||||
|
||||
> **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:** Remove all migrated code from the SaaS layer (environments, apps, deployments, ClickHouse access) and strip it down to a thin vendor management plane: tenant lifecycle, license generation, billing, and Logto organization management.
|
||||
|
||||
**Architecture:** The SaaS retains only vendor-level concerns. All runtime management, observability, and user management is now in the server. The SaaS communicates with server instances exclusively via REST API (ServerApiClient). ClickHouse dependency is removed entirely.
|
||||
|
||||
**Tech Stack:** Java 21, Spring Boot 3.4.3, PostgreSQL 16
|
||||
|
||||
**Repo:** `C:\Users\Hendrik\Documents\projects\cameleer-saas`
|
||||
|
||||
**Prerequisite:** Plans 1-3 must be implemented in cameleer3-server first.
|
||||
|
||||
---
|
||||
|
||||
## Summary of Changes
|
||||
|
||||
### Files to DELETE (migrated to server or no longer needed)
|
||||
|
||||
```
|
||||
src/main/java/net/siegeln/cameleer/saas/environment/
|
||||
├── EnvironmentEntity.java
|
||||
├── EnvironmentService.java
|
||||
├── EnvironmentController.java
|
||||
├── EnvironmentRepository.java
|
||||
├── EnvironmentStatus.java
|
||||
└── dto/
|
||||
├── CreateEnvironmentRequest.java
|
||||
├── UpdateEnvironmentRequest.java
|
||||
└── EnvironmentResponse.java
|
||||
|
||||
src/main/java/net/siegeln/cameleer/saas/app/
|
||||
├── AppEntity.java
|
||||
├── AppService.java
|
||||
├── AppController.java
|
||||
├── AppRepository.java
|
||||
└── dto/
|
||||
├── CreateAppRequest.java
|
||||
└── AppResponse.java
|
||||
|
||||
src/main/java/net/siegeln/cameleer/saas/deployment/
|
||||
├── DeploymentEntity.java
|
||||
├── DeploymentService.java
|
||||
├── DeploymentController.java
|
||||
├── DeploymentRepository.java
|
||||
├── DeploymentExecutor.java
|
||||
├── DesiredStatus.java
|
||||
├── ObservedStatus.java
|
||||
└── dto/
|
||||
└── DeploymentResponse.java
|
||||
|
||||
src/main/java/net/siegeln/cameleer/saas/runtime/
|
||||
├── RuntimeOrchestrator.java
|
||||
├── DockerRuntimeOrchestrator.java
|
||||
├── RuntimeConfig.java
|
||||
├── BuildImageRequest.java
|
||||
├── StartContainerRequest.java
|
||||
├── ContainerStatus.java
|
||||
└── LogConsumer.java
|
||||
|
||||
src/main/java/net/siegeln/cameleer/saas/log/
|
||||
├── ClickHouseConfig.java
|
||||
├── ClickHouseProperties.java
|
||||
├── ContainerLogService.java
|
||||
├── LogController.java
|
||||
└── dto/
|
||||
└── LogEntry.java
|
||||
|
||||
src/main/java/net/siegeln/cameleer/saas/observability/
|
||||
├── AgentStatusService.java
|
||||
├── AgentStatusController.java
|
||||
└── dto/
|
||||
├── AgentStatusResponse.java
|
||||
└── ObservabilityStatusResponse.java
|
||||
```
|
||||
|
||||
### Files to MODIFY
|
||||
|
||||
```
|
||||
src/main/java/net/siegeln/cameleer/saas/config/AsyncConfig.java — remove deploymentExecutor bean
|
||||
src/main/java/net/siegeln/cameleer/saas/tenant/TenantService.java — remove createDefaultForTenant() call
|
||||
src/main/resources/application.yml — remove clickhouse + runtime config sections
|
||||
docker-compose.yml — remove Docker socket mount from SaaS, update routing
|
||||
```
|
||||
|
||||
### Files to KEEP (vendor management plane)
|
||||
|
||||
```
|
||||
src/main/java/net/siegeln/cameleer/saas/tenant/ — Tenant CRUD, lifecycle
|
||||
src/main/java/net/siegeln/cameleer/saas/license/ — License generation
|
||||
src/main/java/net/siegeln/cameleer/saas/identity/ — Logto org management, ServerApiClient
|
||||
src/main/java/net/siegeln/cameleer/saas/config/ — SecurityConfig, SpaController
|
||||
src/main/java/net/siegeln/cameleer/saas/audit/ — Vendor audit logging
|
||||
src/main/java/net/siegeln/cameleer/saas/apikey/ — API key management (if used)
|
||||
ui/ — Vendor management dashboard
|
||||
```
|
||||
|
||||
### Flyway Migrations to KEEP
|
||||
|
||||
The existing migrations (V001-V009) can remain since they're already applied. Add a new cleanup migration:
|
||||
|
||||
```
|
||||
src/main/resources/db/migration/V010__drop_migrated_tables.sql
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Remove ClickHouse Dependency
|
||||
|
||||
- [ ] **Step 1: Delete ClickHouse files**
|
||||
|
||||
```bash
|
||||
rm -rf src/main/java/net/siegeln/cameleer/saas/log/ClickHouseConfig.java
|
||||
rm -rf src/main/java/net/siegeln/cameleer/saas/log/ClickHouseProperties.java
|
||||
rm -rf src/main/java/net/siegeln/cameleer/saas/log/ContainerLogService.java
|
||||
rm -rf src/main/java/net/siegeln/cameleer/saas/log/LogController.java
|
||||
rm -rf src/main/java/net/siegeln/cameleer/saas/log/dto/
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Remove ClickHouse from AgentStatusService**
|
||||
|
||||
Delete `AgentStatusService.java` and `AgentStatusController.java` entirely (agent status is now a server concern).
|
||||
|
||||
```bash
|
||||
rm -rf src/main/java/net/siegeln/cameleer/saas/observability/
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Remove ClickHouse config from application.yml**
|
||||
|
||||
Remove the entire `cameleer.clickhouse:` section.
|
||||
|
||||
- [ ] **Step 4: Remove ClickHouse JDBC dependency from pom.xml**
|
||||
|
||||
Remove:
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>com.clickhouse</groupId>
|
||||
<artifactId>clickhouse-jdbc</artifactId>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
- [ ] **Step 5: Verify build**
|
||||
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer-saas && mvn compile`
|
||||
Expected: BUILD SUCCESS. Fix any remaining import errors.
|
||||
|
||||
- [ ] **Step 6: Commit**
|
||||
|
||||
```bash
|
||||
git add -A
|
||||
git commit -m "feat: remove all ClickHouse dependencies from SaaS layer"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 2: Remove Environment/App/Deployment Code
|
||||
|
||||
- [ ] **Step 1: Delete environment package**
|
||||
|
||||
```bash
|
||||
rm -rf src/main/java/net/siegeln/cameleer/saas/environment/
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Delete app package**
|
||||
|
||||
```bash
|
||||
rm -rf src/main/java/net/siegeln/cameleer/saas/app/
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Delete deployment package**
|
||||
|
||||
```bash
|
||||
rm -rf src/main/java/net/siegeln/cameleer/saas/deployment/
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Delete runtime package**
|
||||
|
||||
```bash
|
||||
rm -rf src/main/java/net/siegeln/cameleer/saas/runtime/
|
||||
```
|
||||
|
||||
- [ ] **Step 5: Remove AsyncConfig deploymentExecutor bean**
|
||||
|
||||
In `AsyncConfig.java`, remove the `deploymentExecutor` bean (or delete AsyncConfig if it only had that bean).
|
||||
|
||||
- [ ] **Step 6: Update TenantService**
|
||||
|
||||
Remove any calls to `EnvironmentService.createDefaultForTenant()` from `TenantService.java`. The server now handles default environment creation.
|
||||
|
||||
- [ ] **Step 7: Remove runtime config from application.yml**
|
||||
|
||||
Remove the entire `cameleer.runtime:` section.
|
||||
|
||||
- [ ] **Step 8: Verify build**
|
||||
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer-saas && mvn compile`
|
||||
Expected: BUILD SUCCESS. Fix any remaining import errors.
|
||||
|
||||
- [ ] **Step 9: Commit**
|
||||
|
||||
```bash
|
||||
git add -A
|
||||
git commit -m "feat: remove migrated environment/app/deployment/runtime code from SaaS"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 3: Database Cleanup Migration
|
||||
|
||||
- [ ] **Step 1: Create cleanup migration**
|
||||
|
||||
```sql
|
||||
-- V010__drop_migrated_tables.sql
|
||||
-- Drop tables that have been migrated to cameleer3-server
|
||||
|
||||
DROP TABLE IF EXISTS deployments CASCADE;
|
||||
DROP TABLE IF EXISTS apps CASCADE;
|
||||
DROP TABLE IF EXISTS environments CASCADE;
|
||||
DROP TABLE IF EXISTS api_keys CASCADE;
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Commit**
|
||||
|
||||
```bash
|
||||
git add src/main/resources/db/migration/V010__drop_migrated_tables.sql
|
||||
git commit -m "feat: drop migrated tables from SaaS database"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 4: Remove Docker Socket Dependency
|
||||
|
||||
- [ ] **Step 1: Update docker-compose.yml**
|
||||
|
||||
Remove from `cameleer-saas` service:
|
||||
```yaml
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- jardata:/data/jars
|
||||
group_add:
|
||||
- "0"
|
||||
```
|
||||
|
||||
The Docker socket mount now belongs to the `cameleer3-server` service instead.
|
||||
|
||||
- [ ] **Step 2: Remove docker-java dependency from pom.xml**
|
||||
|
||||
Remove:
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>com.github.docker-java</groupId>
|
||||
<artifactId>docker-java-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.docker-java</groupId>
|
||||
<artifactId>docker-java-transport-zerodep</artifactId>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add docker-compose.yml pom.xml
|
||||
git commit -m "feat: remove Docker socket dependency from SaaS layer"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 5: Update SaaS UI
|
||||
|
||||
- [ ] **Step 1: Remove environment/app/deployment pages from SaaS frontend**
|
||||
|
||||
Remove pages that now live in the server UI:
|
||||
- `EnvironmentsPage`
|
||||
- `EnvironmentDetailPage`
|
||||
- `AppDetailPage`
|
||||
|
||||
The SaaS UI retains:
|
||||
- `DashboardPage` — vendor overview (tenant list, status)
|
||||
- `AdminTenantsPage` — tenant management
|
||||
- `LicensePage` — license management
|
||||
|
||||
- [ ] **Step 2: Update navigation**
|
||||
|
||||
Remove links to environments/apps/deployments. The SaaS UI should link to the tenant's server instance for those features (e.g., "Open Dashboard" link to `https://{tenant-slug}.cameleer.example.com/server/`).
|
||||
|
||||
- [ ] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add ui/
|
||||
git commit -m "feat: strip SaaS UI to vendor management dashboard"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 6: Expand ServerApiClient
|
||||
|
||||
- [ ] **Step 1: Add provisioning-related API calls**
|
||||
|
||||
The `ServerApiClient` should gain methods for tenant provisioning:
|
||||
|
||||
```java
|
||||
public void pushLicense(String serverEndpoint, String licenseToken) {
|
||||
post(serverEndpoint + "/api/v1/admin/license")
|
||||
.body(Map.of("token", licenseToken))
|
||||
.retrieve()
|
||||
.toBodilessEntity();
|
||||
}
|
||||
|
||||
public Map<String, Object> getHealth(String serverEndpoint) {
|
||||
return get(serverEndpoint + "/api/v1/health")
|
||||
.retrieve()
|
||||
.body(Map.class);
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Commit**
|
||||
|
||||
```bash
|
||||
git add src/main/java/net/siegeln/cameleer/saas/identity/ServerApiClient.java
|
||||
git commit -m "feat: expand ServerApiClient with license push and health check methods"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 7: Write SAAS-INTEGRATION.md
|
||||
|
||||
- [ ] **Step 1: Create integration contract document**
|
||||
|
||||
Create `docs/SAAS-INTEGRATION.md` in the cameleer3-server repo documenting:
|
||||
- Which server API endpoints the SaaS calls
|
||||
- Required auth (M2M token with `server:admin` scope)
|
||||
- License injection mechanism (`POST /api/v1/admin/license`)
|
||||
- Health check endpoint (`GET /api/v1/health`)
|
||||
- What the server exposes vs what the SaaS must never access directly
|
||||
- Env vars the SaaS sets when provisioning a server instance
|
||||
|
||||
- [ ] **Step 2: Commit**
|
||||
|
||||
```bash
|
||||
cd /c/Users/Hendrik/Documents/projects/cameleer3-server
|
||||
git add docs/SAAS-INTEGRATION.md
|
||||
git commit -m "docs: add SaaS integration contract documentation"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 8: Final Verification
|
||||
|
||||
- [ ] **Step 1: Build SaaS**
|
||||
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer-saas && mvn clean verify`
|
||||
Expected: BUILD SUCCESS with reduced dependency footprint.
|
||||
|
||||
- [ ] **Step 2: Verify SaaS starts without ClickHouse**
|
||||
|
||||
The SaaS should start with only PostgreSQL (and Logto). No ClickHouse required.
|
||||
|
||||
- [ ] **Step 3: Verify remaining code footprint**
|
||||
|
||||
The SaaS source should now contain approximately:
|
||||
- `tenant/` — ~4 files
|
||||
- `license/` — ~5 files
|
||||
- `identity/` — ~3 files (LogtoConfig, ServerApiClient, M2M token)
|
||||
- `config/` — ~3 files (SecurityConfig, SpaController, TLS)
|
||||
- `audit/` — ~3 files
|
||||
- `ui/` — stripped dashboard
|
||||
|
||||
Total: ~20 Java files (down from ~75).
|
||||
|
||||
- [ ] **Step 4: Final commit**
|
||||
|
||||
```bash
|
||||
git add -A
|
||||
git commit -m "chore: finalize SaaS cleanup — vendor management plane only"
|
||||
```
|
||||
Reference in New Issue
Block a user