chore: rename cameleer3 to cameleer
Rename Java packages from net.siegeln.cameleer3 to net.siegeln.cameleer, update all references in workflows, Docker configs, docs, and bootstrap. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -80,7 +80,7 @@ Note: Phase 9 (Frontend) can be developed in parallel with Phases 3-8, building
|
||||
**PRD Sections:** 6 (Tenant Provisioning), 11 (Networking & Tenant Isolation)
|
||||
**Gitea Epics:** #3 (Tenant Provisioning), #8 (Networking)
|
||||
**Depends on:** Phase 2
|
||||
**Produces:** Automated tenant provisioning pipeline. Signup creates tenant → Flux HelmRelease generated → namespace provisioned → cameleer3-server deployed → PostgreSQL schema + OpenSearch index created → tenant ACTIVE. NetworkPolicies enforced.
|
||||
**Produces:** Automated tenant provisioning pipeline. Signup creates tenant → Flux HelmRelease generated → namespace provisioned → cameleer-server deployed → PostgreSQL schema + OpenSearch index created → tenant ACTIVE. NetworkPolicies enforced.
|
||||
|
||||
**Key deliverables:**
|
||||
- Provisioning state machine (idempotent, retryable)
|
||||
@@ -91,7 +91,7 @@ Note: Phase 9 (Frontend) can be developed in parallel with Phases 3-8, building
|
||||
- Readiness checking (poll tenant server health)
|
||||
- Tenant lifecycle operations (suspend, reactivate, delete)
|
||||
- K8s NetworkPolicy templates (default deny + allow rules)
|
||||
- Helm chart for cameleer3-server tenant deployment
|
||||
- Helm chart for cameleer-server tenant deployment
|
||||
|
||||
---
|
||||
|
||||
@@ -143,11 +143,11 @@ Note: Phase 9 (Frontend) can be developed in parallel with Phases 3-8, building
|
||||
**PRD Sections:** 8 (Observability Integration)
|
||||
**Gitea Epics:** #6 (Observability Integration), #13 (Exchange Replay — gating only)
|
||||
**Depends on:** Phase 3 (server already deployed per tenant), Phase 2 (license for feature gating)
|
||||
**Produces:** Tenants see their cameleer3-server UI embedded in the SaaS shell. API gateway routes to tenant server. MOAT features gated by license tier.
|
||||
**Produces:** Tenants see their cameleer-server UI embedded in the SaaS shell. API gateway routes to tenant server. MOAT features gated by license tier.
|
||||
|
||||
**Key deliverables:**
|
||||
- Ingress routing rules: `/t/{tenant}/api/*` → tenant's cameleer3-server
|
||||
- cameleer3-server "managed mode" configuration (trust SaaS JWT, report metrics)
|
||||
- Ingress routing rules: `/t/{tenant}/api/*` → tenant's cameleer-server
|
||||
- cameleer-server "managed mode" configuration (trust SaaS JWT, report metrics)
|
||||
- Bootstrap token generation API
|
||||
- MOAT feature gating via license (topology=all, lineage=limited/full, correlation=mid+, debugger=high+, replay=high+)
|
||||
- Server UI embedding approach (iframe or reverse proxy with path rewriting)
|
||||
@@ -211,7 +211,7 @@ Note: Phase 9 (Frontend) can be developed in parallel with Phases 3-8, building
|
||||
- SaaS shell (navigation, tenant switcher, user menu)
|
||||
- Dashboard (platform overview)
|
||||
- Apps list + App deployment page (upload, config, secrets, status, logs, versions)
|
||||
- Observability section (embedded cameleer3-server UI)
|
||||
- Observability section (embedded cameleer-server UI)
|
||||
- Team management pages
|
||||
- Settings pages (tenant config, SSO/OIDC, vault connections)
|
||||
- Billing pages (usage, invoices, plan management)
|
||||
|
||||
@@ -2006,7 +2006,7 @@ available throughout request lifecycle."
|
||||
**Files:**
|
||||
- Create: `src/main/java/net/siegeln/cameleer/saas/config/ForwardAuthController.java`
|
||||
|
||||
This endpoint is called by Traefik's ForwardAuth middleware to validate requests routed to non-platform services (e.g., cameleer3-server). It validates the JWT, resolves the tenant, and returns tenant context headers.
|
||||
This endpoint is called by Traefik's ForwardAuth middleware to validate requests routed to non-platform services (e.g., cameleer-server). It validates the JWT, resolves the tenant, and returns tenant context headers.
|
||||
|
||||
- [ ] **Step 1: Create ForwardAuthController**
|
||||
|
||||
@@ -2455,8 +2455,8 @@ services:
|
||||
networks:
|
||||
- cameleer
|
||||
|
||||
cameleer3-server:
|
||||
image: ${CAMELEER3_SERVER_IMAGE:-gitea.siegeln.net/cameleer/cameleer3-server}:${VERSION:-latest}
|
||||
cameleer-server:
|
||||
image: ${CAMELEER_SERVER_IMAGE:-gitea.siegeln.net/cameleer/cameleer-server}:${VERSION:-latest}
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
postgres:
|
||||
@@ -2539,9 +2539,9 @@ git add docker-compose.yml docker-compose.dev.yml traefik.yml docker/init-databa
|
||||
git commit -m "feat: add Docker Compose production stack with Traefik + Logto
|
||||
|
||||
7-container stack: Traefik (reverse proxy), PostgreSQL (shared),
|
||||
Logto (identity), cameleer-saas (control plane), cameleer3-server
|
||||
Logto (identity), cameleer-saas (control plane), cameleer-server
|
||||
(observability), ClickHouse (traces). ForwardAuth middleware for
|
||||
tenant-aware routing to cameleer3-server."
|
||||
tenant-aware routing to cameleer-server."
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
> **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:** Customers can upload a Camel JAR, the platform builds a container image with cameleer3 agent auto-injected, and deploys it to a logical environment with full lifecycle management.
|
||||
**Goal:** Customers can upload a Camel JAR, the platform builds a container image with cameleer agent auto-injected, and deploys it to a logical environment with full lifecycle management.
|
||||
|
||||
**Architecture:** Environment → App → Deployment entity hierarchy. `RuntimeOrchestrator` interface with `DockerRuntimeOrchestrator` (docker-java) implementation. Async deployment pipeline with status polling. Container logs streamed to ClickHouse. Pre-built `cameleer-runtime-base` image for fast (~1-3s) customer image builds.
|
||||
|
||||
@@ -164,8 +164,8 @@ public class RuntimeConfig {
|
||||
@Value("${cameleer.runtime.bootstrap-token:${CAMELEER_AUTH_TOKEN:}}")
|
||||
private String bootstrapToken;
|
||||
|
||||
@Value("${cameleer.runtime.cameleer3-server-endpoint:http://cameleer3-server:8081}")
|
||||
private String cameleer3ServerEndpoint;
|
||||
@Value("${cameleer.runtime.cameleer-server-endpoint:http://cameleer-server:8081}")
|
||||
private String cameleerServerEndpoint;
|
||||
|
||||
public long getMaxJarSize() { return maxJarSize; }
|
||||
public String getJarStoragePath() { return jarStoragePath; }
|
||||
@@ -177,7 +177,7 @@ public class RuntimeConfig {
|
||||
public String getContainerMemoryLimit() { return containerMemoryLimit; }
|
||||
public int getContainerCpuShares() { return containerCpuShares; }
|
||||
public String getBootstrapToken() { return bootstrapToken; }
|
||||
public String getCameleer3ServerEndpoint() { return cameleer3ServerEndpoint; }
|
||||
public String getCameleerServerEndpoint() { return cameleerServerEndpoint; }
|
||||
|
||||
public long parseMemoryLimitBytes() {
|
||||
var limit = containerMemoryLimit.trim().toLowerCase();
|
||||
@@ -270,7 +270,7 @@ Append to the existing `cameleer:` section in `src/main/resources/application.ym
|
||||
container-memory-limit: ${CAMELEER_CONTAINER_MEMORY_LIMIT:512m}
|
||||
container-cpu-shares: ${CAMELEER_CONTAINER_CPU_SHARES:512}
|
||||
bootstrap-token: ${CAMELEER_AUTH_TOKEN:}
|
||||
cameleer3-server-endpoint: ${CAMELEER3_SERVER_ENDPOINT:http://cameleer3-server:8081}
|
||||
cameleer-server-endpoint: ${CAMELEER_SERVER_ENDPOINT:http://cameleer-server:8081}
|
||||
clickhouse:
|
||||
url: ${CLICKHOUSE_URL:jdbc:clickhouse://clickhouse:8123/cameleer}
|
||||
```
|
||||
@@ -2788,7 +2788,7 @@ public class DeploymentService {
|
||||
var envVars = Map.of(
|
||||
"CAMELEER_AUTH_TOKEN", env.getBootstrapToken(),
|
||||
"CAMELEER_EXPORT_TYPE", "HTTP",
|
||||
"CAMELEER_EXPORT_ENDPOINT", runtimeConfig.getCameleer3ServerEndpoint(),
|
||||
"CAMELEER_EXPORT_ENDPOINT", runtimeConfig.getCameleerServerEndpoint(),
|
||||
"CAMELEER_APPLICATION_ID", app.getSlug(),
|
||||
"CAMELEER_ENVIRONMENT_ID", env.getSlug(),
|
||||
"CAMELEER_DISPLAY_NAME", containerName);
|
||||
@@ -3418,7 +3418,7 @@ volumes:
|
||||
Add to the cameleer-saas service environment:
|
||||
```yaml
|
||||
CAMELEER_AUTH_TOKEN: ${CAMELEER_AUTH_TOKEN:-default-bootstrap-token}
|
||||
CAMELEER3_SERVER_ENDPOINT: http://cameleer3-server:8081
|
||||
CAMELEER_SERVER_ENDPOINT: http://cameleer-server:8081
|
||||
CLICKHOUSE_URL: jdbc:clickhouse://clickhouse:8123/cameleer
|
||||
```
|
||||
|
||||
@@ -3427,7 +3427,7 @@ Add to the cameleer-saas service volumes:
|
||||
- jardata:/data/jars
|
||||
```
|
||||
|
||||
Add `CAMELEER_AUTH_TOKEN` to the cameleer3-server service environment:
|
||||
Add `CAMELEER_AUTH_TOKEN` to the cameleer-server service environment:
|
||||
```yaml
|
||||
CAMELEER_AUTH_TOKEN: ${CAMELEER_AUTH_TOKEN:-default-bootstrap-token}
|
||||
```
|
||||
@@ -3448,7 +3448,7 @@ FROM eclipse-temurin:21-jre-alpine
|
||||
WORKDIR /app
|
||||
|
||||
# Agent JAR is copied during CI build from Gitea Maven registry
|
||||
# ARG AGENT_JAR=cameleer3-agent-1.0-SNAPSHOT-shaded.jar
|
||||
# ARG AGENT_JAR=cameleer-agent-1.0-SNAPSHOT-shaded.jar
|
||||
COPY agent.jar /app/agent.jar
|
||||
|
||||
ENTRYPOINT exec java \
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
> **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:** Complete the deploy → hit endpoint → see traces loop. Serve the existing cameleer3-server dashboard, add agent connectivity verification, enable optional inbound HTTP routing for customer apps, and wire up observability data health checks.
|
||||
**Goal:** Complete the deploy → hit endpoint → see traces loop. Serve the existing cameleer-server dashboard, add agent connectivity verification, enable optional inbound HTTP routing for customer apps, and wire up observability data health checks.
|
||||
|
||||
**Architecture:** Wiring phase — cameleer3-server already has full observability. Phase 4 adds Traefik routing for the dashboard + customer app endpoints, new API endpoints in cameleer-saas for agent-status and observability-status, and configures `CAMELEER_TENANT_ID` on the server.
|
||||
**Architecture:** Wiring phase — cameleer-server already has full observability. Phase 4 adds Traefik routing for the dashboard + customer app endpoints, new API endpoints in cameleer-saas for agent-status and observability-status, and configures `CAMELEER_TENANT_ID` on the server.
|
||||
|
||||
**Tech Stack:** Spring Boot 3.4.3, docker-java 3.4.1, ClickHouse JDBC, Traefik v3 labels, Spring RestClient
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
### New Files
|
||||
|
||||
- `src/main/java/net/siegeln/cameleer/saas/observability/AgentStatusService.java` — Queries cameleer3-server for agent registration
|
||||
- `src/main/java/net/siegeln/cameleer/saas/observability/AgentStatusService.java` — Queries cameleer-server for agent registration
|
||||
- `src/main/java/net/siegeln/cameleer/saas/observability/AgentStatusController.java` — Agent status + observability status endpoints
|
||||
- `src/main/java/net/siegeln/cameleer/saas/observability/dto/AgentStatusResponse.java` — Response DTO
|
||||
- `src/main/java/net/siegeln/cameleer/saas/observability/dto/ObservabilityStatusResponse.java` — Response DTO
|
||||
@@ -359,7 +359,7 @@ class AgentStatusServiceTest {
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
when(runtimeConfig.getCameleer3ServerEndpoint()).thenReturn("http://cameleer3-server:8081");
|
||||
when(runtimeConfig.getCameleerServerEndpoint()).thenReturn("http://cameleer-server:8081");
|
||||
agentStatusService = new AgentStatusService(appRepository, environmentRepository, runtimeConfig);
|
||||
}
|
||||
|
||||
@@ -439,7 +439,7 @@ public class AgentStatusService {
|
||||
this.environmentRepository = environmentRepository;
|
||||
this.runtimeConfig = runtimeConfig;
|
||||
this.restClient = RestClient.builder()
|
||||
.baseUrl(runtimeConfig.getCameleer3ServerEndpoint())
|
||||
.baseUrl(runtimeConfig.getCameleerServerEndpoint())
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -475,7 +475,7 @@ public class AgentStatusService {
|
||||
return new AgentStatusResponse(false, "NOT_REGISTERED", null,
|
||||
List.of(), app.getSlug(), env.getSlug());
|
||||
} catch (Exception e) {
|
||||
log.warn("Failed to query agent status from cameleer3-server: {}", e.getMessage());
|
||||
log.warn("Failed to query agent status from cameleer-server: {}", e.getMessage());
|
||||
return new AgentStatusResponse(false, "UNKNOWN", null,
|
||||
List.of(), app.getSlug(), env.getSlug());
|
||||
}
|
||||
@@ -651,28 +651,28 @@ public class ConnectivityHealthCheck {
|
||||
|
||||
@EventListener(ApplicationReadyEvent.class)
|
||||
public void verifyConnectivity() {
|
||||
checkCameleer3Server();
|
||||
checkCameleerServer();
|
||||
}
|
||||
|
||||
private void checkCameleer3Server() {
|
||||
private void checkCameleerServer() {
|
||||
try {
|
||||
var client = RestClient.builder()
|
||||
.baseUrl(runtimeConfig.getCameleer3ServerEndpoint())
|
||||
.baseUrl(runtimeConfig.getCameleerServerEndpoint())
|
||||
.build();
|
||||
var response = client.get()
|
||||
.uri("/actuator/health")
|
||||
.retrieve()
|
||||
.toBodilessEntity();
|
||||
if (response.getStatusCode().is2xxSuccessful()) {
|
||||
log.info("cameleer3-server connectivity: OK ({})",
|
||||
runtimeConfig.getCameleer3ServerEndpoint());
|
||||
log.info("cameleer-server connectivity: OK ({})",
|
||||
runtimeConfig.getCameleerServerEndpoint());
|
||||
} else {
|
||||
log.warn("cameleer3-server connectivity: HTTP {} ({})",
|
||||
response.getStatusCode(), runtimeConfig.getCameleer3ServerEndpoint());
|
||||
log.warn("cameleer-server connectivity: HTTP {} ({})",
|
||||
response.getStatusCode(), runtimeConfig.getCameleerServerEndpoint());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("cameleer3-server connectivity: FAILED ({}) - {}",
|
||||
runtimeConfig.getCameleer3ServerEndpoint(), e.getMessage());
|
||||
log.warn("cameleer-server connectivity: FAILED ({}) - {}",
|
||||
runtimeConfig.getCameleerServerEndpoint(), e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -686,7 +686,7 @@ Run: `mvn compile -B -q`
|
||||
|
||||
```bash
|
||||
git add src/main/java/net/siegeln/cameleer/saas/observability/ConnectivityHealthCheck.java
|
||||
git commit -m "feat: add cameleer3-server startup connectivity check"
|
||||
git commit -m "feat: add cameleer-server startup connectivity check"
|
||||
```
|
||||
|
||||
---
|
||||
@@ -700,7 +700,7 @@ git commit -m "feat: add cameleer3-server startup connectivity check"
|
||||
|
||||
- [ ] **Step 1: Update docker-compose.yml — add dashboard route and CAMELEER_TENANT_ID**
|
||||
|
||||
In the `cameleer3-server` service:
|
||||
In the `cameleer-server` service:
|
||||
|
||||
Add to environment section:
|
||||
```yaml
|
||||
@@ -774,7 +774,7 @@ git commit -m "docs: update HOWTO with observability dashboard, routing, and age
|
||||
|
||||
| Spec Requirement | Task |
|
||||
|---|---|
|
||||
| Serve cameleer3-server dashboard via Traefik | Task 7 (dashboard Traefik labels) |
|
||||
| Serve cameleer-server dashboard via Traefik | Task 7 (dashboard Traefik labels) |
|
||||
| CAMELEER_TENANT_ID configuration | Task 7 (docker-compose env) |
|
||||
| Agent connectivity verification endpoint | Task 4 (AgentStatusService + Controller) |
|
||||
| Observability data health endpoint | Task 4 (ObservabilityStatusResponse) |
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
**Goal:** Build a React SPA for managing tenants, environments, apps, and deployments. All backend APIs exist — this is the UI layer.
|
||||
|
||||
**Architecture:** React 19 + Vite + React Router + Zustand + TanStack Query + @cameleer/design-system. Sidebar layout matching cameleer3-server SPA. Shared Logto OIDC session. RBAC on all actions. Lives in `ui/` directory, built into Spring Boot static resources.
|
||||
**Architecture:** React 19 + Vite + React Router + Zustand + TanStack Query + @cameleer/design-system. Sidebar layout matching cameleer-server SPA. Shared Logto OIDC session. RBAC on all actions. Lives in `ui/` directory, built into Spring Boot static resources.
|
||||
|
||||
**Tech Stack:** React 19, Vite 8, TypeScript, React Router 7, Zustand, TanStack React Query, @cameleer/design-system 0.1.31, Lucide React
|
||||
|
||||
@@ -332,7 +332,7 @@ git commit -m "feat: scaffold React SPA with Vite, design system, and TypeScript
|
||||
|
||||
- [ ] **Step 1: Create auth-store.ts**
|
||||
|
||||
Zustand store for auth state. Same localStorage keys as cameleer3-server SPA for SSO.
|
||||
Zustand store for auth state. Same localStorage keys as cameleer-server SPA for SSO.
|
||||
|
||||
```typescript
|
||||
import { create } from 'zustand';
|
||||
@@ -1145,7 +1145,7 @@ git commit -m "feat: add SPA controller, Traefik route, CI frontend build, and H
|
||||
|---|---|
|
||||
| Project scaffolding (Vite, React, TS, design system) | Task 1 |
|
||||
| TypeScript API types | Task 1 |
|
||||
| Auth store (Zustand, same keys as cameleer3-server) | Task 2 |
|
||||
| Auth store (Zustand, same keys as cameleer-server) | Task 2 |
|
||||
| Login / Logto OIDC redirect / callback | Task 2 |
|
||||
| Protected route | Task 2 |
|
||||
| API client with auth middleware | Task 3 |
|
||||
|
||||
@@ -2,35 +2,35 @@
|
||||
|
||||
> **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:** Replace the incoherent three-system auth in cameleer-saas with Logto-centric architecture, and add OIDC resource server support to cameleer3-server for M2M.
|
||||
**Goal:** Replace the incoherent three-system auth in cameleer-saas with Logto-centric architecture, and add OIDC resource server support to cameleer-server for M2M.
|
||||
|
||||
**Architecture:** Logto is the single identity provider for all humans. Spring OAuth2 Resource Server validates Logto JWTs in both the SaaS platform and cameleer3-server. Agents authenticate with per-environment API keys exchanged for server-issued JWTs. Ed25519 command signing is unchanged. Zero trust: every service validates tokens independently via JWKS.
|
||||
**Architecture:** Logto is the single identity provider for all humans. Spring OAuth2 Resource Server validates Logto JWTs in both the SaaS platform and cameleer-server. Agents authenticate with per-environment API keys exchanged for server-issued JWTs. Ed25519 command signing is unchanged. Zero trust: every service validates tokens independently via JWKS.
|
||||
|
||||
**Tech Stack:** Spring Boot 3.4, Spring Security OAuth2 Resource Server, Nimbus JOSE+JWT, Logto, React + @logto/react, Zustand, PostgreSQL, Flyway
|
||||
|
||||
**Spec:** `docs/superpowers/specs/2026-04-05-auth-overhaul-design.md`
|
||||
|
||||
**Repos:**
|
||||
- cameleer3-server: `C:\Users\Hendrik\Documents\projects\cameleer3-server` (Phase 1)
|
||||
- cameleer-server: `C:\Users\Hendrik\Documents\projects\cameleer-server` (Phase 1)
|
||||
- cameleer-saas: `C:\Users\Hendrik\Documents\projects\cameleer-saas` (Phases 2-3)
|
||||
- cameleer3 (agent): NO CHANGES
|
||||
- cameleer (agent): NO CHANGES
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: cameleer3-server — OIDC Resource Server Support
|
||||
## Phase 1: cameleer-server — OIDC Resource Server Support
|
||||
|
||||
All Phase 1 work is in `C:\Users\Hendrik\Documents\projects\cameleer3-server`.
|
||||
All Phase 1 work is in `C:\Users\Hendrik\Documents\projects\cameleer-server`.
|
||||
|
||||
### Task 1: Add OAuth2 Resource Server dependency and config properties
|
||||
|
||||
**Files:**
|
||||
- Modify: `cameleer3-server-app/pom.xml`
|
||||
- Modify: `cameleer3-server-app/src/main/resources/application.yml`
|
||||
- Modify: `cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/SecurityProperties.java`
|
||||
- Modify: `cameleer-server-app/pom.xml`
|
||||
- Modify: `cameleer-server-app/src/main/resources/application.yml`
|
||||
- Modify: `cameleer-server-app/src/main/java/com/cameleer/server/app/security/SecurityProperties.java`
|
||||
|
||||
- [ ] **Step 1: Add dependency to pom.xml**
|
||||
|
||||
In `cameleer3-server-app/pom.xml`, add after the `spring-boot-starter-security` dependency (around line 88):
|
||||
In `cameleer-server-app/pom.xml`, add after the `spring-boot-starter-security` dependency (around line 88):
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
@@ -41,7 +41,7 @@ In `cameleer3-server-app/pom.xml`, add after the `spring-boot-starter-security`
|
||||
|
||||
- [ ] **Step 2: Add OIDC properties to application.yml**
|
||||
|
||||
In `cameleer3-server-app/src/main/resources/application.yml`, add two new properties under the `security:` block (after line 52):
|
||||
In `cameleer-server-app/src/main/resources/application.yml`, add two new properties under the `security:` block (after line 52):
|
||||
|
||||
```yaml
|
||||
oidc-issuer-uri: ${CAMELEER_OIDC_ISSUER_URI:}
|
||||
@@ -50,7 +50,7 @@ In `cameleer3-server-app/src/main/resources/application.yml`, add two new proper
|
||||
|
||||
- [ ] **Step 3: Add fields to SecurityProperties.java**
|
||||
|
||||
In `cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/SecurityProperties.java`, add after the `jwtSecret` field (line 19):
|
||||
In `cameleer-server-app/src/main/java/com/cameleer/server/app/security/SecurityProperties.java`, add after the `jwtSecret` field (line 19):
|
||||
|
||||
```java
|
||||
private String oidcIssuerUri;
|
||||
@@ -64,13 +64,13 @@ public void setOidcAudience(String oidcAudience) { this.oidcAudience = oidcAudie
|
||||
|
||||
- [ ] **Step 4: Verify build compiles**
|
||||
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer3-server && ./mvnw compile -pl cameleer3-server-app -q`
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer-server && ./mvnw compile -pl cameleer-server-app -q`
|
||||
Expected: BUILD SUCCESS
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-app/pom.xml cameleer3-server-app/src/main/resources/application.yml cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/SecurityProperties.java
|
||||
git add cameleer-server-app/pom.xml cameleer-server-app/src/main/resources/application.yml cameleer-server-app/src/main/java/com/cameleer/server/app/security/SecurityProperties.java
|
||||
git commit -m "feat: add oauth2-resource-server dependency and OIDC config properties"
|
||||
```
|
||||
|
||||
@@ -79,14 +79,14 @@ git commit -m "feat: add oauth2-resource-server dependency and OIDC config prope
|
||||
### Task 2: Add conditional OIDC JwtDecoder bean
|
||||
|
||||
**Files:**
|
||||
- Modify: `cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/SecurityBeanConfig.java`
|
||||
- Modify: `cameleer-server-app/src/main/java/com/cameleer/server/app/security/SecurityBeanConfig.java`
|
||||
|
||||
- [ ] **Step 1: Write the failing test**
|
||||
|
||||
Create `cameleer3-server-app/src/test/java/com/cameleer3/server/app/security/OidcJwtDecoderBeanTest.java`:
|
||||
Create `cameleer-server-app/src/test/java/com/cameleer/server/app/security/OidcJwtDecoderBeanTest.java`:
|
||||
|
||||
```java
|
||||
package com.cameleer3.server.app.security;
|
||||
package com.cameleer.server.app.security;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.security.oauth2.jwt.JwtDecoder;
|
||||
@@ -123,12 +123,12 @@ class OidcJwtDecoderBeanTest {
|
||||
|
||||
- [ ] **Step 2: Run test to verify it fails**
|
||||
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer3-server && ./mvnw test -pl cameleer3-server-app -Dtest=OidcJwtDecoderBeanTest -q`
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer-server && ./mvnw test -pl cameleer-server-app -Dtest=OidcJwtDecoderBeanTest -q`
|
||||
Expected: FAIL — method `oidcJwtDecoder` does not exist
|
||||
|
||||
- [ ] **Step 3: Add the oidcJwtDecoder method to SecurityBeanConfig**
|
||||
|
||||
In `cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/SecurityBeanConfig.java`, add these imports at the top:
|
||||
In `cameleer-server-app/src/main/java/com/cameleer/server/app/security/SecurityBeanConfig.java`, add these imports at the top:
|
||||
|
||||
```java
|
||||
import com.nimbusds.jose.JWSAlgorithm;
|
||||
@@ -216,13 +216,13 @@ Update the test to match: the test calls `config.oidcJwtDecoder(properties)` dir
|
||||
|
||||
- [ ] **Step 5: Run test to verify it passes**
|
||||
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer3-server && ./mvnw test -pl cameleer3-server-app -Dtest=OidcJwtDecoderBeanTest -q`
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer-server && ./mvnw test -pl cameleer-server-app -Dtest=OidcJwtDecoderBeanTest -q`
|
||||
Expected: PASS
|
||||
|
||||
- [ ] **Step 6: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/SecurityBeanConfig.java cameleer3-server-app/src/test/java/com/cameleer3/server/app/security/OidcJwtDecoderBeanTest.java
|
||||
git add cameleer-server-app/src/main/java/com/cameleer/server/app/security/SecurityBeanConfig.java cameleer-server-app/src/test/java/com/cameleer/server/app/security/OidcJwtDecoderBeanTest.java
|
||||
git commit -m "feat: add conditional OIDC JwtDecoder factory for Logto token validation"
|
||||
```
|
||||
|
||||
@@ -231,18 +231,18 @@ git commit -m "feat: add conditional OIDC JwtDecoder factory for Logto token val
|
||||
### Task 3: Update JwtAuthenticationFilter with OIDC fallback
|
||||
|
||||
**Files:**
|
||||
- Modify: `cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/JwtAuthenticationFilter.java`
|
||||
- Modify: `cameleer-server-app/src/main/java/com/cameleer/server/app/security/JwtAuthenticationFilter.java`
|
||||
|
||||
- [ ] **Step 1: Write the failing test**
|
||||
|
||||
Create `cameleer3-server-app/src/test/java/com/cameleer3/server/app/security/JwtAuthenticationFilterOidcTest.java`:
|
||||
Create `cameleer-server-app/src/test/java/com/cameleer/server/app/security/JwtAuthenticationFilterOidcTest.java`:
|
||||
|
||||
```java
|
||||
package com.cameleer3.server.app.security;
|
||||
package com.cameleer.server.app.security;
|
||||
|
||||
import com.cameleer3.server.core.agent.AgentRegistryService;
|
||||
import com.cameleer3.server.core.security.InvalidTokenException;
|
||||
import com.cameleer3.server.core.security.JwtService;
|
||||
import com.cameleer.server.core.agent.AgentRegistryService;
|
||||
import com.cameleer.server.core.security.InvalidTokenException;
|
||||
import com.cameleer.server.core.security.JwtService;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@@ -369,19 +369,19 @@ class JwtAuthenticationFilterOidcTest {
|
||||
|
||||
- [ ] **Step 2: Run test to verify it fails**
|
||||
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer3-server && ./mvnw test -pl cameleer3-server-app -Dtest=JwtAuthenticationFilterOidcTest -q`
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer-server && ./mvnw test -pl cameleer-server-app -Dtest=JwtAuthenticationFilterOidcTest -q`
|
||||
Expected: FAIL — constructor doesn't accept 3 args
|
||||
|
||||
- [ ] **Step 3: Update JwtAuthenticationFilter**
|
||||
|
||||
Replace `cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/JwtAuthenticationFilter.java` with:
|
||||
Replace `cameleer-server-app/src/main/java/com/cameleer/server/app/security/JwtAuthenticationFilter.java` with:
|
||||
|
||||
```java
|
||||
package com.cameleer3.server.app.security;
|
||||
package com.cameleer.server.app.security;
|
||||
|
||||
import com.cameleer3.server.core.agent.AgentRegistryService;
|
||||
import com.cameleer3.server.core.security.JwtService;
|
||||
import com.cameleer3.server.core.security.JwtService.JwtValidationResult;
|
||||
import com.cameleer.server.core.agent.AgentRegistryService;
|
||||
import com.cameleer.server.core.security.JwtService;
|
||||
import com.cameleer.server.core.security.JwtService.JwtValidationResult;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
@@ -508,13 +508,13 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
|
||||
- [ ] **Step 4: Run tests**
|
||||
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer3-server && ./mvnw test -pl cameleer3-server-app -Dtest=JwtAuthenticationFilterOidcTest -q`
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer-server && ./mvnw test -pl cameleer-server-app -Dtest=JwtAuthenticationFilterOidcTest -q`
|
||||
Expected: PASS (all 4 tests)
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/JwtAuthenticationFilter.java cameleer3-server-app/src/test/java/com/cameleer3/server/app/security/JwtAuthenticationFilterOidcTest.java
|
||||
git add cameleer-server-app/src/main/java/com/cameleer/server/app/security/JwtAuthenticationFilter.java cameleer-server-app/src/test/java/com/cameleer/server/app/security/JwtAuthenticationFilterOidcTest.java
|
||||
git commit -m "feat: add OIDC token fallback to JwtAuthenticationFilter"
|
||||
```
|
||||
|
||||
@@ -523,8 +523,8 @@ git commit -m "feat: add OIDC token fallback to JwtAuthenticationFilter"
|
||||
### Task 4: Wire OIDC decoder into SecurityConfig
|
||||
|
||||
**Files:**
|
||||
- Modify: `cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/SecurityConfig.java`
|
||||
- Modify: `cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/SecurityBeanConfig.java`
|
||||
- Modify: `cameleer-server-app/src/main/java/com/cameleer/server/app/security/SecurityConfig.java`
|
||||
- Modify: `cameleer-server-app/src/main/java/com/cameleer/server/app/security/SecurityBeanConfig.java`
|
||||
|
||||
- [ ] **Step 1: Add OIDC decoder bean creation to SecurityBeanConfig**
|
||||
|
||||
@@ -595,13 +595,13 @@ import org.springframework.security.oauth2.jwt.JwtDecoder;
|
||||
|
||||
- [ ] **Step 3: Run existing tests**
|
||||
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer3-server && ./mvnw test -pl cameleer3-server-app -q`
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer-server && ./mvnw test -pl cameleer-server-app -q`
|
||||
Expected: All existing tests PASS (no OIDC env vars set, decoder is null, filter behaves as before)
|
||||
|
||||
- [ ] **Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/SecurityConfig.java cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/SecurityBeanConfig.java
|
||||
git add cameleer-server-app/src/main/java/com/cameleer/server/app/security/SecurityConfig.java cameleer-server-app/src/main/java/com/cameleer/server/app/security/SecurityBeanConfig.java
|
||||
git commit -m "feat: wire optional OIDC JwtDecoder into security filter chain"
|
||||
```
|
||||
|
||||
@@ -1685,9 +1685,9 @@ In `docker-compose.yml`, remove these two labels from `cameleer-saas` (lines 122
|
||||
- traefik.http.services.forwardauth.loadbalancer.server.port=8080
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Remove ForwardAuth middleware from cameleer3-server**
|
||||
- [ ] **Step 2: Remove ForwardAuth middleware from cameleer-server**
|
||||
|
||||
In `docker-compose.yml`, remove the forward-auth middleware labels from `cameleer3-server` (lines 158-159):
|
||||
In `docker-compose.yml`, remove the forward-auth middleware labels from `cameleer-server` (lines 158-159):
|
||||
|
||||
```yaml
|
||||
- traefik.http.routers.observe.middlewares=forward-auth
|
||||
@@ -1719,7 +1719,7 @@ In `cameleer-saas` environment, remove:
|
||||
CAMELEER_AUTH_TOKEN: ${CAMELEER_AUTH_TOKEN:-default-bootstrap-token}
|
||||
```
|
||||
|
||||
In `cameleer3-server` environment, add:
|
||||
In `cameleer-server` environment, add:
|
||||
```yaml
|
||||
CAMELEER_OIDC_ISSUER_URI: ${LOGTO_ISSUER_URI:-http://logto:3001/oidc}
|
||||
CAMELEER_OIDC_AUDIENCE: ${CAMELEER_OIDC_AUDIENCE:-https://api.cameleer.local}
|
||||
|
||||
@@ -8,41 +8,41 @@
|
||||
|
||||
**Tech Stack:** Java 17, Spring Boot 3.4.3, PostgreSQL 16, Flyway, JUnit 5, Testcontainers, AssertJ
|
||||
|
||||
**Repo:** `C:\Users\Hendrik\Documents\projects\cameleer3-server`
|
||||
**Repo:** `C:\Users\Hendrik\Documents\projects\cameleer-server`
|
||||
|
||||
---
|
||||
|
||||
## File Map
|
||||
|
||||
### New Files
|
||||
- `cameleer3-server-app/src/main/resources/db/migration/V2__claim_mapping.sql`
|
||||
- `cameleer3-server-core/src/main/java/com/cameleer3/server/core/rbac/ClaimMappingRule.java`
|
||||
- `cameleer3-server-core/src/main/java/com/cameleer3/server/core/rbac/ClaimMappingRepository.java`
|
||||
- `cameleer3-server-core/src/main/java/com/cameleer3/server/core/rbac/ClaimMappingService.java`
|
||||
- `cameleer3-server-core/src/main/java/com/cameleer3/server/core/rbac/AssignmentOrigin.java`
|
||||
- `cameleer3-server-app/src/main/java/com/cameleer3/server/app/storage/PostgresClaimMappingRepository.java`
|
||||
- `cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/ClaimMappingAdminController.java`
|
||||
- `cameleer3-server-app/src/test/java/com/cameleer3/server/core/rbac/ClaimMappingServiceTest.java`
|
||||
- `cameleer3-server-app/src/test/java/com/cameleer3/server/app/controller/ClaimMappingAdminControllerIT.java`
|
||||
- `cameleer3-server-app/src/test/java/com/cameleer3/server/app/security/OidcOnlyModeIT.java`
|
||||
- `cameleer-server-app/src/main/resources/db/migration/V2__claim_mapping.sql`
|
||||
- `cameleer-server-core/src/main/java/com/cameleer/server/core/rbac/ClaimMappingRule.java`
|
||||
- `cameleer-server-core/src/main/java/com/cameleer/server/core/rbac/ClaimMappingRepository.java`
|
||||
- `cameleer-server-core/src/main/java/com/cameleer/server/core/rbac/ClaimMappingService.java`
|
||||
- `cameleer-server-core/src/main/java/com/cameleer/server/core/rbac/AssignmentOrigin.java`
|
||||
- `cameleer-server-app/src/main/java/com/cameleer/server/app/storage/PostgresClaimMappingRepository.java`
|
||||
- `cameleer-server-app/src/main/java/com/cameleer/server/app/controller/ClaimMappingAdminController.java`
|
||||
- `cameleer-server-app/src/test/java/com/cameleer/server/core/rbac/ClaimMappingServiceTest.java`
|
||||
- `cameleer-server-app/src/test/java/com/cameleer/server/app/controller/ClaimMappingAdminControllerIT.java`
|
||||
- `cameleer-server-app/src/test/java/com/cameleer/server/app/security/OidcOnlyModeIT.java`
|
||||
|
||||
### Modified Files
|
||||
- `cameleer3-server-app/src/main/resources/db/migration/V1__init.sql` — no changes (immutable)
|
||||
- `cameleer3-server-app/src/main/java/com/cameleer3/server/app/rbac/RbacServiceImpl.java` — add origin-aware query methods
|
||||
- `cameleer3-server-app/src/main/java/com/cameleer3/server/app/storage/PostgresUserRepository.java` — add origin-aware queries
|
||||
- `cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/OidcAuthController.java` — replace syncOidcRoles with claim mapping
|
||||
- `cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/JwtAuthenticationFilter.java` — disable internal token path in OIDC-only mode
|
||||
- `cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/SecurityConfig.java` — conditional endpoint registration
|
||||
- `cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/UserAdminController.java` — disable in OIDC-only mode
|
||||
- `cameleer3-server-app/src/main/java/com/cameleer3/server/app/config/AgentRegistryBeanConfig.java` — wire ClaimMappingService
|
||||
- `cameleer3-server-app/src/main/resources/application.yml` — no new properties needed (OIDC config already exists)
|
||||
- `cameleer-server-app/src/main/resources/db/migration/V1__init.sql` — no changes (immutable)
|
||||
- `cameleer-server-app/src/main/java/com/cameleer/server/app/rbac/RbacServiceImpl.java` — add origin-aware query methods
|
||||
- `cameleer-server-app/src/main/java/com/cameleer/server/app/storage/PostgresUserRepository.java` — add origin-aware queries
|
||||
- `cameleer-server-app/src/main/java/com/cameleer/server/app/security/OidcAuthController.java` — replace syncOidcRoles with claim mapping
|
||||
- `cameleer-server-app/src/main/java/com/cameleer/server/app/security/JwtAuthenticationFilter.java` — disable internal token path in OIDC-only mode
|
||||
- `cameleer-server-app/src/main/java/com/cameleer/server/app/security/SecurityConfig.java` — conditional endpoint registration
|
||||
- `cameleer-server-app/src/main/java/com/cameleer/server/app/controller/UserAdminController.java` — disable in OIDC-only mode
|
||||
- `cameleer-server-app/src/main/java/com/cameleer/server/app/config/AgentRegistryBeanConfig.java` — wire ClaimMappingService
|
||||
- `cameleer-server-app/src/main/resources/application.yml` — no new properties needed (OIDC config already exists)
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Database Migration — Add Origin Tracking and Claim Mapping Rules
|
||||
|
||||
**Files:**
|
||||
- Create: `cameleer3-server-app/src/main/resources/db/migration/V2__claim_mapping.sql`
|
||||
- Create: `cameleer-server-app/src/main/resources/db/migration/V2__claim_mapping.sql`
|
||||
|
||||
- [ ] **Step 1: Write the migration**
|
||||
|
||||
@@ -90,14 +90,14 @@ CREATE INDEX idx_user_groups_origin ON user_groups(user_id, origin);
|
||||
|
||||
- [ ] **Step 2: Run migration to verify**
|
||||
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer3-server && mvn flyway:migrate -pl cameleer3-server-app -Dflyway.url=jdbc:postgresql://localhost:5432/cameleer3 -Dflyway.user=cameleer -Dflyway.password=cameleer_dev`
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer-server && mvn flyway:migrate -pl cameleer-server-app -Dflyway.url=jdbc:postgresql://localhost:5432/cameleer -Dflyway.user=cameleer -Dflyway.password=cameleer_dev`
|
||||
|
||||
If no local PostgreSQL, verify syntax by running the existing test suite which uses Testcontainers.
|
||||
|
||||
- [ ] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-app/src/main/resources/db/migration/V2__claim_mapping.sql
|
||||
git add cameleer-server-app/src/main/resources/db/migration/V2__claim_mapping.sql
|
||||
git commit -m "feat: add claim mapping rules table and origin tracking to RBAC assignments"
|
||||
```
|
||||
|
||||
@@ -106,14 +106,14 @@ git commit -m "feat: add claim mapping rules table and origin tracking to RBAC a
|
||||
### Task 2: Core Domain — ClaimMappingRule, AssignmentOrigin, Repository Interface
|
||||
|
||||
**Files:**
|
||||
- Create: `cameleer3-server-core/src/main/java/com/cameleer3/server/core/rbac/AssignmentOrigin.java`
|
||||
- Create: `cameleer3-server-core/src/main/java/com/cameleer3/server/core/rbac/ClaimMappingRule.java`
|
||||
- Create: `cameleer3-server-core/src/main/java/com/cameleer3/server/core/rbac/ClaimMappingRepository.java`
|
||||
- Create: `cameleer-server-core/src/main/java/com/cameleer/server/core/rbac/AssignmentOrigin.java`
|
||||
- Create: `cameleer-server-core/src/main/java/com/cameleer/server/core/rbac/ClaimMappingRule.java`
|
||||
- Create: `cameleer-server-core/src/main/java/com/cameleer/server/core/rbac/ClaimMappingRepository.java`
|
||||
|
||||
- [ ] **Step 1: Create AssignmentOrigin enum**
|
||||
|
||||
```java
|
||||
package com.cameleer3.server.core.rbac;
|
||||
package com.cameleer.server.core.rbac;
|
||||
|
||||
public enum AssignmentOrigin {
|
||||
direct, managed
|
||||
@@ -123,7 +123,7 @@ public enum AssignmentOrigin {
|
||||
- [ ] **Step 2: Create ClaimMappingRule record**
|
||||
|
||||
```java
|
||||
package com.cameleer3.server.core.rbac;
|
||||
package com.cameleer.server.core.rbac;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.UUID;
|
||||
@@ -146,7 +146,7 @@ public record ClaimMappingRule(
|
||||
- [ ] **Step 3: Create ClaimMappingRepository interface**
|
||||
|
||||
```java
|
||||
package com.cameleer3.server.core.rbac;
|
||||
package com.cameleer.server.core.rbac;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -164,9 +164,9 @@ public interface ClaimMappingRepository {
|
||||
- [ ] **Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-core/src/main/java/com/cameleer3/server/core/rbac/AssignmentOrigin.java
|
||||
git add cameleer3-server-core/src/main/java/com/cameleer3/server/core/rbac/ClaimMappingRule.java
|
||||
git add cameleer3-server-core/src/main/java/com/cameleer3/server/core/rbac/ClaimMappingRepository.java
|
||||
git add cameleer-server-core/src/main/java/com/cameleer/server/core/rbac/AssignmentOrigin.java
|
||||
git add cameleer-server-core/src/main/java/com/cameleer/server/core/rbac/ClaimMappingRule.java
|
||||
git add cameleer-server-core/src/main/java/com/cameleer/server/core/rbac/ClaimMappingRepository.java
|
||||
git commit -m "feat: add ClaimMappingRule domain model and repository interface"
|
||||
```
|
||||
|
||||
@@ -175,13 +175,13 @@ git commit -m "feat: add ClaimMappingRule domain model and repository interface"
|
||||
### Task 3: Core Domain — ClaimMappingService
|
||||
|
||||
**Files:**
|
||||
- Create: `cameleer3-server-core/src/main/java/com/cameleer3/server/core/rbac/ClaimMappingService.java`
|
||||
- Create: `cameleer3-server-app/src/test/java/com/cameleer3/server/core/rbac/ClaimMappingServiceTest.java`
|
||||
- Create: `cameleer-server-core/src/main/java/com/cameleer/server/core/rbac/ClaimMappingService.java`
|
||||
- Create: `cameleer-server-app/src/test/java/com/cameleer/server/core/rbac/ClaimMappingServiceTest.java`
|
||||
|
||||
- [ ] **Step 1: Write tests for ClaimMappingService**
|
||||
|
||||
```java
|
||||
package com.cameleer3.server.core.rbac;
|
||||
package com.cameleer.server.core.rbac;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -300,13 +300,13 @@ class ClaimMappingServiceTest {
|
||||
|
||||
- [ ] **Step 2: Run tests to verify they fail**
|
||||
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer3-server && mvn test -pl cameleer3-server-app -Dtest=ClaimMappingServiceTest -Dsurefire.failIfNoSpecifiedTests=false`
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer-server && mvn test -pl cameleer-server-app -Dtest=ClaimMappingServiceTest -Dsurefire.failIfNoSpecifiedTests=false`
|
||||
Expected: Compilation error — ClaimMappingService does not exist yet.
|
||||
|
||||
- [ ] **Step 3: Implement ClaimMappingService**
|
||||
|
||||
```java
|
||||
package com.cameleer3.server.core.rbac;
|
||||
package com.cameleer.server.core.rbac;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -377,14 +377,14 @@ public class ClaimMappingService {
|
||||
|
||||
- [ ] **Step 4: Run tests to verify they pass**
|
||||
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer3-server && mvn test -pl cameleer3-server-app -Dtest=ClaimMappingServiceTest`
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer-server && mvn test -pl cameleer-server-app -Dtest=ClaimMappingServiceTest`
|
||||
Expected: All 7 tests PASS.
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-core/src/main/java/com/cameleer3/server/core/rbac/ClaimMappingService.java
|
||||
git add cameleer3-server-app/src/test/java/com/cameleer3/server/core/rbac/ClaimMappingServiceTest.java
|
||||
git add cameleer-server-core/src/main/java/com/cameleer/server/core/rbac/ClaimMappingService.java
|
||||
git add cameleer-server-app/src/test/java/com/cameleer/server/core/rbac/ClaimMappingServiceTest.java
|
||||
git commit -m "feat: implement ClaimMappingService with equals/contains/regex matching"
|
||||
```
|
||||
|
||||
@@ -393,15 +393,15 @@ git commit -m "feat: implement ClaimMappingService with equals/contains/regex ma
|
||||
### Task 4: PostgreSQL Repository — ClaimMappingRepository Implementation
|
||||
|
||||
**Files:**
|
||||
- Create: `cameleer3-server-app/src/main/java/com/cameleer3/server/app/storage/PostgresClaimMappingRepository.java`
|
||||
- Create: `cameleer-server-app/src/main/java/com/cameleer/server/app/storage/PostgresClaimMappingRepository.java`
|
||||
|
||||
- [ ] **Step 1: Implement PostgresClaimMappingRepository**
|
||||
|
||||
```java
|
||||
package com.cameleer3.server.app.storage;
|
||||
package com.cameleer.server.app.storage;
|
||||
|
||||
import com.cameleer3.server.core.rbac.ClaimMappingRepository;
|
||||
import com.cameleer3.server.core.rbac.ClaimMappingRule;
|
||||
import com.cameleer.server.core.rbac.ClaimMappingRepository;
|
||||
import com.cameleer.server.core.rbac.ClaimMappingRule;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
import java.util.List;
|
||||
@@ -479,7 +479,7 @@ public class PostgresClaimMappingRepository implements ClaimMappingRepository {
|
||||
|
||||
- [ ] **Step 2: Wire the bean in AgentRegistryBeanConfig (or a new RbacBeanConfig)**
|
||||
|
||||
Add to `cameleer3-server-app/src/main/java/com/cameleer3/server/app/config/AgentRegistryBeanConfig.java` (or create a new `RbacBeanConfig.java`):
|
||||
Add to `cameleer-server-app/src/main/java/com/cameleer/server/app/config/AgentRegistryBeanConfig.java` (or create a new `RbacBeanConfig.java`):
|
||||
|
||||
```java
|
||||
@Bean
|
||||
@@ -496,8 +496,8 @@ public ClaimMappingService claimMappingService() {
|
||||
- [ ] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-app/src/main/java/com/cameleer3/server/app/storage/PostgresClaimMappingRepository.java
|
||||
git add cameleer3-server-app/src/main/java/com/cameleer3/server/app/config/AgentRegistryBeanConfig.java
|
||||
git add cameleer-server-app/src/main/java/com/cameleer/server/app/storage/PostgresClaimMappingRepository.java
|
||||
git add cameleer-server-app/src/main/java/com/cameleer/server/app/config/AgentRegistryBeanConfig.java
|
||||
git commit -m "feat: implement PostgresClaimMappingRepository and wire beans"
|
||||
```
|
||||
|
||||
@@ -506,11 +506,11 @@ git commit -m "feat: implement PostgresClaimMappingRepository and wire beans"
|
||||
### Task 5: Modify RbacServiceImpl — Origin-Aware Assignments
|
||||
|
||||
**Files:**
|
||||
- Modify: `cameleer3-server-app/src/main/java/com/cameleer3/server/app/rbac/RbacServiceImpl.java`
|
||||
- Modify: `cameleer-server-app/src/main/java/com/cameleer/server/app/rbac/RbacServiceImpl.java`
|
||||
|
||||
- [ ] **Step 1: Add managed assignment methods to RbacService interface**
|
||||
|
||||
In `cameleer3-server-core/src/main/java/com/cameleer3/server/core/rbac/RbacService.java`, add:
|
||||
In `cameleer-server-core/src/main/java/com/cameleer/server/core/rbac/RbacService.java`, add:
|
||||
|
||||
```java
|
||||
void clearManagedAssignments(String userId);
|
||||
@@ -592,14 +592,14 @@ public List<RoleSummary> getDirectRolesForUser(String userId) {
|
||||
|
||||
- [ ] **Step 5: Run existing tests**
|
||||
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer3-server && mvn test -pl cameleer3-server-app`
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer-server && mvn test -pl cameleer-server-app`
|
||||
Expected: All existing tests still pass (migration adds columns with defaults).
|
||||
|
||||
- [ ] **Step 6: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-core/src/main/java/com/cameleer3/server/core/rbac/RbacService.java
|
||||
git add cameleer3-server-app/src/main/java/com/cameleer3/server/app/rbac/RbacServiceImpl.java
|
||||
git add cameleer-server-core/src/main/java/com/cameleer/server/core/rbac/RbacService.java
|
||||
git add cameleer-server-app/src/main/java/com/cameleer/server/app/rbac/RbacServiceImpl.java
|
||||
git commit -m "feat: add origin-aware managed/direct assignment methods to RbacService"
|
||||
```
|
||||
|
||||
@@ -608,7 +608,7 @@ git commit -m "feat: add origin-aware managed/direct assignment methods to RbacS
|
||||
### Task 6: Modify OidcAuthController — Replace syncOidcRoles with Claim Mapping
|
||||
|
||||
**Files:**
|
||||
- Modify: `cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/OidcAuthController.java`
|
||||
- Modify: `cameleer-server-app/src/main/java/com/cameleer/server/app/security/OidcAuthController.java`
|
||||
|
||||
- [ ] **Step 1: Inject ClaimMappingService and ClaimMappingRepository**
|
||||
|
||||
@@ -676,13 +676,13 @@ Note: `extractAllClaims` needs to be added to `OidcTokenExchanger` — it return
|
||||
|
||||
- [ ] **Step 4: Run existing tests**
|
||||
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer3-server && mvn test -pl cameleer3-server-app`
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer-server && mvn test -pl cameleer-server-app`
|
||||
Expected: PASS (OIDC tests may need adjustment if they test syncOidcRoles directly).
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/OidcAuthController.java
|
||||
git add cameleer-server-app/src/main/java/com/cameleer/server/app/security/OidcAuthController.java
|
||||
git commit -m "feat: replace syncOidcRoles with claim mapping evaluation on OIDC login"
|
||||
```
|
||||
|
||||
@@ -691,8 +691,8 @@ git commit -m "feat: replace syncOidcRoles with claim mapping evaluation on OIDC
|
||||
### Task 7: OIDC-Only Mode — Disable Local Auth When OIDC Configured
|
||||
|
||||
**Files:**
|
||||
- Modify: `cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/SecurityConfig.java`
|
||||
- Modify: `cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/JwtAuthenticationFilter.java`
|
||||
- Modify: `cameleer-server-app/src/main/java/com/cameleer/server/app/security/SecurityConfig.java`
|
||||
- Modify: `cameleer-server-app/src/main/java/com/cameleer/server/app/security/JwtAuthenticationFilter.java`
|
||||
|
||||
- [ ] **Step 1: Add isOidcEnabled() helper to SecurityConfig**
|
||||
|
||||
@@ -760,15 +760,15 @@ public ResponseEntity<?> resetPassword(@PathVariable String userId, @RequestBody
|
||||
|
||||
- [ ] **Step 5: Run full test suite**
|
||||
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer3-server && mvn test -pl cameleer3-server-app`
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer-server && mvn test -pl cameleer-server-app`
|
||||
Expected: PASS.
|
||||
|
||||
- [ ] **Step 6: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/SecurityConfig.java
|
||||
git add cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/JwtAuthenticationFilter.java
|
||||
git add cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/UserAdminController.java
|
||||
git add cameleer-server-app/src/main/java/com/cameleer/server/app/security/SecurityConfig.java
|
||||
git add cameleer-server-app/src/main/java/com/cameleer/server/app/security/JwtAuthenticationFilter.java
|
||||
git add cameleer-server-app/src/main/java/com/cameleer/server/app/controller/UserAdminController.java
|
||||
git commit -m "feat: disable local auth when OIDC is configured (resource server mode)"
|
||||
```
|
||||
|
||||
@@ -777,15 +777,15 @@ git commit -m "feat: disable local auth when OIDC is configured (resource server
|
||||
### Task 8: Claim Mapping Admin Controller
|
||||
|
||||
**Files:**
|
||||
- Create: `cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/ClaimMappingAdminController.java`
|
||||
- Create: `cameleer-server-app/src/main/java/com/cameleer/server/app/controller/ClaimMappingAdminController.java`
|
||||
|
||||
- [ ] **Step 1: Implement the controller**
|
||||
|
||||
```java
|
||||
package com.cameleer3.server.app.controller;
|
||||
package com.cameleer.server.app.controller;
|
||||
|
||||
import com.cameleer3.server.core.rbac.ClaimMappingRepository;
|
||||
import com.cameleer3.server.core.rbac.ClaimMappingRule;
|
||||
import com.cameleer.server.core.rbac.ClaimMappingRepository;
|
||||
import com.cameleer.server.core.rbac.ClaimMappingRule;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -867,13 +867,13 @@ In `SecurityConfig.filterChain()`, the `/api/v1/admin/**` path already requires
|
||||
|
||||
- [ ] **Step 3: Run full test suite**
|
||||
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer3-server && mvn test -pl cameleer3-server-app`
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer-server && mvn test -pl cameleer-server-app`
|
||||
Expected: PASS.
|
||||
|
||||
- [ ] **Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/ClaimMappingAdminController.java
|
||||
git add cameleer-server-app/src/main/java/com/cameleer/server/app/controller/ClaimMappingAdminController.java
|
||||
git commit -m "feat: add ClaimMappingAdminController for CRUD on mapping rules"
|
||||
```
|
||||
|
||||
@@ -882,14 +882,14 @@ git commit -m "feat: add ClaimMappingAdminController for CRUD on mapping rules"
|
||||
### Task 9: Integration Test — Claim Mapping End-to-End
|
||||
|
||||
**Files:**
|
||||
- Create: `cameleer3-server-app/src/test/java/com/cameleer3/server/app/controller/ClaimMappingAdminControllerIT.java`
|
||||
- Create: `cameleer-server-app/src/test/java/com/cameleer/server/app/controller/ClaimMappingAdminControllerIT.java`
|
||||
|
||||
- [ ] **Step 1: Write integration test**
|
||||
|
||||
```java
|
||||
package com.cameleer3.server.app.controller;
|
||||
package com.cameleer.server.app.controller;
|
||||
|
||||
import com.cameleer3.server.app.AbstractPostgresIT;
|
||||
import com.cameleer.server.app.AbstractPostgresIT;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@@ -954,13 +954,13 @@ class ClaimMappingAdminControllerIT extends AbstractPostgresIT {
|
||||
|
||||
- [ ] **Step 2: Run integration tests**
|
||||
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer3-server && mvn test -pl cameleer3-server-app -Dtest=ClaimMappingAdminControllerIT`
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer-server && mvn test -pl cameleer-server-app -Dtest=ClaimMappingAdminControllerIT`
|
||||
Expected: PASS.
|
||||
|
||||
- [ ] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-app/src/test/java/com/cameleer3/server/app/controller/ClaimMappingAdminControllerIT.java
|
||||
git add cameleer-server-app/src/test/java/com/cameleer/server/app/controller/ClaimMappingAdminControllerIT.java
|
||||
git commit -m "test: add integration tests for claim mapping admin API"
|
||||
```
|
||||
|
||||
@@ -970,12 +970,12 @@ git commit -m "test: add integration tests for claim mapping admin API"
|
||||
|
||||
- [ ] **Step 1: Run all tests**
|
||||
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer3-server && mvn clean verify`
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer-server && mvn clean verify`
|
||||
Expected: All tests PASS. Build succeeds.
|
||||
|
||||
- [ ] **Step 2: Verify migration applies cleanly on fresh database**
|
||||
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer3-server && mvn test -pl cameleer3-server-app -Dtest=AbstractPostgresIT`
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer-server && mvn test -pl cameleer-server-app -Dtest=AbstractPostgresIT`
|
||||
Expected: Testcontainers starts fresh PostgreSQL, Flyway applies V1 + V2, context loads.
|
||||
|
||||
- [ ] **Step 3: Commit any remaining fixes**
|
||||
|
||||
@@ -8,37 +8,37 @@
|
||||
|
||||
**Tech Stack:** Java 17, Spring Boot 3.4.3, Ed25519 (JDK built-in), Nimbus JOSE JWT, JUnit 5, AssertJ
|
||||
|
||||
**Repo:** `C:\Users\Hendrik\Documents\projects\cameleer3-server`
|
||||
**Repo:** `C:\Users\Hendrik\Documents\projects\cameleer-server`
|
||||
|
||||
---
|
||||
|
||||
## File Map
|
||||
|
||||
### New Files
|
||||
- `cameleer3-server-core/src/main/java/com/cameleer3/server/core/license/LicenseInfo.java`
|
||||
- `cameleer3-server-core/src/main/java/com/cameleer3/server/core/license/LicenseValidator.java`
|
||||
- `cameleer3-server-core/src/main/java/com/cameleer3/server/core/license/LicenseGate.java`
|
||||
- `cameleer3-server-core/src/main/java/com/cameleer3/server/core/license/Feature.java`
|
||||
- `cameleer3-server-app/src/main/java/com/cameleer3/server/app/config/LicenseBeanConfig.java`
|
||||
- `cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/LicenseAdminController.java`
|
||||
- `cameleer3-server-app/src/test/java/com/cameleer3/server/core/license/LicenseValidatorTest.java`
|
||||
- `cameleer3-server-app/src/test/java/com/cameleer3/server/core/license/LicenseGateTest.java`
|
||||
- `cameleer-server-core/src/main/java/com/cameleer/server/core/license/LicenseInfo.java`
|
||||
- `cameleer-server-core/src/main/java/com/cameleer/server/core/license/LicenseValidator.java`
|
||||
- `cameleer-server-core/src/main/java/com/cameleer/server/core/license/LicenseGate.java`
|
||||
- `cameleer-server-core/src/main/java/com/cameleer/server/core/license/Feature.java`
|
||||
- `cameleer-server-app/src/main/java/com/cameleer/server/app/config/LicenseBeanConfig.java`
|
||||
- `cameleer-server-app/src/main/java/com/cameleer/server/app/controller/LicenseAdminController.java`
|
||||
- `cameleer-server-app/src/test/java/com/cameleer/server/core/license/LicenseValidatorTest.java`
|
||||
- `cameleer-server-app/src/test/java/com/cameleer/server/core/license/LicenseGateTest.java`
|
||||
|
||||
### Modified Files
|
||||
- `cameleer3-server-app/src/main/resources/application.yml` — add license config properties
|
||||
- `cameleer-server-app/src/main/resources/application.yml` — add license config properties
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Core Domain — LicenseInfo, Feature Enum
|
||||
|
||||
**Files:**
|
||||
- Create: `cameleer3-server-core/src/main/java/com/cameleer3/server/core/license/Feature.java`
|
||||
- Create: `cameleer3-server-core/src/main/java/com/cameleer3/server/core/license/LicenseInfo.java`
|
||||
- Create: `cameleer-server-core/src/main/java/com/cameleer/server/core/license/Feature.java`
|
||||
- Create: `cameleer-server-core/src/main/java/com/cameleer/server/core/license/LicenseInfo.java`
|
||||
|
||||
- [ ] **Step 1: Create Feature enum**
|
||||
|
||||
```java
|
||||
package com.cameleer3.server.core.license;
|
||||
package com.cameleer.server.core.license;
|
||||
|
||||
public enum Feature {
|
||||
topology,
|
||||
@@ -52,7 +52,7 @@ public enum Feature {
|
||||
- [ ] **Step 2: Create LicenseInfo record**
|
||||
|
||||
```java
|
||||
package com.cameleer3.server.core.license;
|
||||
package com.cameleer.server.core.license;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
@@ -87,8 +87,8 @@ public record LicenseInfo(
|
||||
- [ ] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-core/src/main/java/com/cameleer3/server/core/license/Feature.java
|
||||
git add cameleer3-server-core/src/main/java/com/cameleer3/server/core/license/LicenseInfo.java
|
||||
git add cameleer-server-core/src/main/java/com/cameleer/server/core/license/Feature.java
|
||||
git add cameleer-server-core/src/main/java/com/cameleer/server/core/license/LicenseInfo.java
|
||||
git commit -m "feat: add LicenseInfo and Feature domain model"
|
||||
```
|
||||
|
||||
@@ -97,13 +97,13 @@ git commit -m "feat: add LicenseInfo and Feature domain model"
|
||||
### Task 2: LicenseValidator — Ed25519 JWT Verification
|
||||
|
||||
**Files:**
|
||||
- Create: `cameleer3-server-core/src/main/java/com/cameleer3/server/core/license/LicenseValidator.java`
|
||||
- Create: `cameleer3-server-app/src/test/java/com/cameleer3/server/core/license/LicenseValidatorTest.java`
|
||||
- Create: `cameleer-server-core/src/main/java/com/cameleer/server/core/license/LicenseValidator.java`
|
||||
- Create: `cameleer-server-app/src/test/java/com/cameleer/server/core/license/LicenseValidatorTest.java`
|
||||
|
||||
- [ ] **Step 1: Write tests**
|
||||
|
||||
```java
|
||||
package com.cameleer3.server.core.license;
|
||||
package com.cameleer.server.core.license;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -194,13 +194,13 @@ class LicenseValidatorTest {
|
||||
|
||||
- [ ] **Step 2: Run tests to verify they fail**
|
||||
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer3-server && mvn test -pl cameleer3-server-app -Dtest=LicenseValidatorTest -Dsurefire.failIfNoSpecifiedTests=false`
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer-server && mvn test -pl cameleer-server-app -Dtest=LicenseValidatorTest -Dsurefire.failIfNoSpecifiedTests=false`
|
||||
Expected: Compilation error — LicenseValidator does not exist.
|
||||
|
||||
- [ ] **Step 3: Implement LicenseValidator**
|
||||
|
||||
```java
|
||||
package com.cameleer3.server.core.license;
|
||||
package com.cameleer.server.core.license;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
@@ -298,14 +298,14 @@ public class LicenseValidator {
|
||||
|
||||
- [ ] **Step 4: Run tests**
|
||||
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer3-server && mvn test -pl cameleer3-server-app -Dtest=LicenseValidatorTest`
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer-server && mvn test -pl cameleer-server-app -Dtest=LicenseValidatorTest`
|
||||
Expected: All 3 tests PASS.
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-core/src/main/java/com/cameleer3/server/core/license/LicenseValidator.java
|
||||
git add cameleer3-server-app/src/test/java/com/cameleer3/server/core/license/LicenseValidatorTest.java
|
||||
git add cameleer-server-core/src/main/java/com/cameleer/server/core/license/LicenseValidator.java
|
||||
git add cameleer-server-app/src/test/java/com/cameleer/server/core/license/LicenseValidatorTest.java
|
||||
git commit -m "feat: implement LicenseValidator with Ed25519 signature verification"
|
||||
```
|
||||
|
||||
@@ -314,13 +314,13 @@ git commit -m "feat: implement LicenseValidator with Ed25519 signature verificat
|
||||
### Task 3: LicenseGate — Feature Check Service
|
||||
|
||||
**Files:**
|
||||
- Create: `cameleer3-server-core/src/main/java/com/cameleer3/server/core/license/LicenseGate.java`
|
||||
- Create: `cameleer3-server-app/src/test/java/com/cameleer3/server/core/license/LicenseGateTest.java`
|
||||
- Create: `cameleer-server-core/src/main/java/com/cameleer/server/core/license/LicenseGate.java`
|
||||
- Create: `cameleer-server-app/src/test/java/com/cameleer/server/core/license/LicenseGateTest.java`
|
||||
|
||||
- [ ] **Step 1: Write tests**
|
||||
|
||||
```java
|
||||
package com.cameleer3.server.core.license;
|
||||
package com.cameleer.server.core.license;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -366,7 +366,7 @@ class LicenseGateTest {
|
||||
- [ ] **Step 2: Implement LicenseGate**
|
||||
|
||||
```java
|
||||
package com.cameleer3.server.core.license;
|
||||
package com.cameleer.server.core.license;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -405,14 +405,14 @@ public class LicenseGate {
|
||||
|
||||
- [ ] **Step 3: Run tests**
|
||||
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer3-server && mvn test -pl cameleer3-server-app -Dtest=LicenseGateTest`
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer-server && mvn test -pl cameleer-server-app -Dtest=LicenseGateTest`
|
||||
Expected: PASS.
|
||||
|
||||
- [ ] **Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-core/src/main/java/com/cameleer3/server/core/license/LicenseGate.java
|
||||
git add cameleer3-server-app/src/test/java/com/cameleer3/server/core/license/LicenseGateTest.java
|
||||
git add cameleer-server-core/src/main/java/com/cameleer/server/core/license/LicenseGate.java
|
||||
git add cameleer-server-app/src/test/java/com/cameleer/server/core/license/LicenseGateTest.java
|
||||
git commit -m "feat: implement LicenseGate for feature checking"
|
||||
```
|
||||
|
||||
@@ -421,8 +421,8 @@ git commit -m "feat: implement LicenseGate for feature checking"
|
||||
### Task 4: License Loading — Bean Config and Startup
|
||||
|
||||
**Files:**
|
||||
- Create: `cameleer3-server-app/src/main/java/com/cameleer3/server/app/config/LicenseBeanConfig.java`
|
||||
- Modify: `cameleer3-server-app/src/main/resources/application.yml`
|
||||
- Create: `cameleer-server-app/src/main/java/com/cameleer/server/app/config/LicenseBeanConfig.java`
|
||||
- Modify: `cameleer-server-app/src/main/resources/application.yml`
|
||||
|
||||
- [ ] **Step 1: Add license config properties to application.yml**
|
||||
|
||||
@@ -436,11 +436,11 @@ license:
|
||||
- [ ] **Step 2: Implement LicenseBeanConfig**
|
||||
|
||||
```java
|
||||
package com.cameleer3.server.app.config;
|
||||
package com.cameleer.server.app.config;
|
||||
|
||||
import com.cameleer3.server.core.license.LicenseGate;
|
||||
import com.cameleer3.server.core.license.LicenseInfo;
|
||||
import com.cameleer3.server.core.license.LicenseValidator;
|
||||
import com.cameleer.server.core.license.LicenseGate;
|
||||
import com.cameleer.server.core.license.LicenseInfo;
|
||||
import com.cameleer.server.core.license.LicenseValidator;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@@ -509,8 +509,8 @@ public class LicenseBeanConfig {
|
||||
- [ ] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-app/src/main/java/com/cameleer3/server/app/config/LicenseBeanConfig.java
|
||||
git add cameleer3-server-app/src/main/resources/application.yml
|
||||
git add cameleer-server-app/src/main/java/com/cameleer/server/app/config/LicenseBeanConfig.java
|
||||
git add cameleer-server-app/src/main/resources/application.yml
|
||||
git commit -m "feat: add license loading at startup from env var or file"
|
||||
```
|
||||
|
||||
@@ -519,16 +519,16 @@ git commit -m "feat: add license loading at startup from env var or file"
|
||||
### Task 5: License Admin API — Runtime License Update
|
||||
|
||||
**Files:**
|
||||
- Create: `cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/LicenseAdminController.java`
|
||||
- Create: `cameleer-server-app/src/main/java/com/cameleer/server/app/controller/LicenseAdminController.java`
|
||||
|
||||
- [ ] **Step 1: Implement controller**
|
||||
|
||||
```java
|
||||
package com.cameleer3.server.app.controller;
|
||||
package com.cameleer.server.app.controller;
|
||||
|
||||
import com.cameleer3.server.core.license.LicenseGate;
|
||||
import com.cameleer3.server.core.license.LicenseInfo;
|
||||
import com.cameleer3.server.core.license.LicenseValidator;
|
||||
import com.cameleer.server.core.license.LicenseGate;
|
||||
import com.cameleer.server.core.license.LicenseInfo;
|
||||
import com.cameleer.server.core.license.LicenseValidator;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@@ -581,13 +581,13 @@ public class LicenseAdminController {
|
||||
|
||||
- [ ] **Step 2: Run full test suite**
|
||||
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer3-server && mvn clean verify`
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer-server && mvn clean verify`
|
||||
Expected: PASS.
|
||||
|
||||
- [ ] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/LicenseAdminController.java
|
||||
git add cameleer-server-app/src/main/java/com/cameleer/server/app/controller/LicenseAdminController.java
|
||||
git commit -m "feat: add license admin API for runtime license updates"
|
||||
```
|
||||
|
||||
@@ -611,5 +611,5 @@ public ResponseEntity<?> listDebugSessions() {
|
||||
|
||||
- [ ] **Step 2: Final verification**
|
||||
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer3-server && mvn clean verify`
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer-server && mvn clean verify`
|
||||
Expected: All tests PASS.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Plan 3: Runtime Management in the Server
|
||||
|
||||
> **Status: COMPLETED** — Verified 2026-04-09. All runtime management fully ported to cameleer3-server with enhancements beyond the original plan.
|
||||
> **Status: COMPLETED** — Verified 2026-04-09. All runtime management fully ported to cameleer-server with enhancements beyond the original 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 (`- [x]`) syntax for tracking.
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
**Tech Stack:** Java 17, Spring Boot 3.4.3, docker-java (zerodep transport), PostgreSQL 16, Flyway, JUnit 5, Testcontainers
|
||||
|
||||
**Repo:** `C:\Users\Hendrik\Documents\projects\cameleer3-server`
|
||||
**Repo:** `C:\Users\Hendrik\Documents\projects\cameleer-server`
|
||||
|
||||
**Source reference:** Code ported from `C:\Users\Hendrik\Documents\projects\cameleer-saas` (environment, app, deployment, runtime packages)
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
|
||||
## File Map
|
||||
|
||||
### New Files — Core Module (`cameleer3-server-core`)
|
||||
### New Files — Core Module (`cameleer-server-core`)
|
||||
|
||||
```
|
||||
src/main/java/com/cameleer3/server/core/runtime/
|
||||
src/main/java/com/cameleer/server/core/runtime/
|
||||
├── Environment.java Record: id, slug, displayName, status, createdAt
|
||||
├── EnvironmentStatus.java Enum: ACTIVE, SUSPENDED
|
||||
├── EnvironmentRepository.java Interface: CRUD + findBySlug
|
||||
@@ -42,10 +42,10 @@ src/main/java/com/cameleer3/server/core/runtime/
|
||||
└── RoutingMode.java Enum: path, subdomain
|
||||
```
|
||||
|
||||
### New Files — App Module (`cameleer3-server-app`)
|
||||
### New Files — App Module (`cameleer-server-app`)
|
||||
|
||||
```
|
||||
src/main/java/com/cameleer3/server/app/runtime/
|
||||
src/main/java/com/cameleer/server/app/runtime/
|
||||
├── DockerRuntimeOrchestrator.java Docker implementation using docker-java
|
||||
├── DisabledRuntimeOrchestrator.java No-op implementation (observability-only mode)
|
||||
├── RuntimeOrchestratorAutoConfig.java @Configuration: auto-detects Docker vs K8s vs disabled
|
||||
@@ -53,13 +53,13 @@ src/main/java/com/cameleer3/server/app/runtime/
|
||||
├── JarStorageService.java File-system JAR storage with versioning
|
||||
└── ContainerLogCollector.java Collects Docker container stdout/stderr
|
||||
|
||||
src/main/java/com/cameleer3/server/app/storage/
|
||||
src/main/java/com/cameleer/server/app/storage/
|
||||
├── PostgresEnvironmentRepository.java
|
||||
├── PostgresAppRepository.java
|
||||
├── PostgresAppVersionRepository.java
|
||||
└── PostgresDeploymentRepository.java
|
||||
|
||||
src/main/java/com/cameleer3/server/app/controller/
|
||||
src/main/java/com/cameleer/server/app/controller/
|
||||
├── EnvironmentAdminController.java CRUD endpoints under /api/v1/admin/environments
|
||||
├── AppController.java App + version CRUD + JAR upload
|
||||
└── DeploymentController.java Deploy, stop, restart, promote, logs
|
||||
@@ -70,7 +70,7 @@ src/main/resources/db/migration/
|
||||
|
||||
### Modified Files
|
||||
- `pom.xml` (parent) — add docker-java dependency
|
||||
- `cameleer3-server-app/pom.xml` — add docker-java dependency
|
||||
- `cameleer-server-app/pom.xml` — add docker-java dependency
|
||||
- `application.yml` — add runtime config properties
|
||||
|
||||
---
|
||||
@@ -78,7 +78,7 @@ src/main/resources/db/migration/
|
||||
### Task 1: Add docker-java Dependency
|
||||
|
||||
**Files:**
|
||||
- Modify: `cameleer3-server-app/pom.xml`
|
||||
- Modify: `cameleer-server-app/pom.xml`
|
||||
|
||||
- [x] **Step 1: Add docker-java dependency**
|
||||
|
||||
@@ -97,13 +97,13 @@ src/main/resources/db/migration/
|
||||
|
||||
- [x] **Step 2: Verify build**
|
||||
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer3-server && mvn compile -pl cameleer3-server-app`
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer-server && mvn compile -pl cameleer-server-app`
|
||||
Expected: BUILD SUCCESS.
|
||||
|
||||
- [x] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-app/pom.xml
|
||||
git add cameleer-server-app/pom.xml
|
||||
git commit -m "chore: add docker-java dependency for runtime orchestration"
|
||||
```
|
||||
|
||||
@@ -112,7 +112,7 @@ git commit -m "chore: add docker-java dependency for runtime orchestration"
|
||||
### Task 2: Database Migration — Runtime Management Tables
|
||||
|
||||
**Files:**
|
||||
- Create: `cameleer3-server-app/src/main/resources/db/migration/V3__runtime_management.sql`
|
||||
- Create: `cameleer-server-app/src/main/resources/db/migration/V3__runtime_management.sql`
|
||||
|
||||
- [x] **Step 1: Write migration**
|
||||
|
||||
@@ -176,7 +176,7 @@ INSERT INTO environments (slug, display_name) VALUES ('default', 'Default');
|
||||
- [x] **Step 2: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-app/src/main/resources/db/migration/V3__runtime_management.sql
|
||||
git add cameleer-server-app/src/main/resources/db/migration/V3__runtime_management.sql
|
||||
git commit -m "feat: add runtime management database schema (environments, apps, versions, deployments)"
|
||||
```
|
||||
|
||||
@@ -185,36 +185,36 @@ git commit -m "feat: add runtime management database schema (environments, apps,
|
||||
### Task 3: Core Domain — Environment, App, AppVersion, Deployment Records
|
||||
|
||||
**Files:**
|
||||
- Create all records in `cameleer3-server-core/src/main/java/com/cameleer3/server/core/runtime/`
|
||||
- Create all records in `cameleer-server-core/src/main/java/com/cameleer/server/core/runtime/`
|
||||
|
||||
- [x] **Step 1: Create all domain records**
|
||||
|
||||
```java
|
||||
// Environment.java
|
||||
package com.cameleer3.server.core.runtime;
|
||||
package com.cameleer.server.core.runtime;
|
||||
import java.time.Instant;
|
||||
import java.util.UUID;
|
||||
public record Environment(UUID id, String slug, String displayName, EnvironmentStatus status, Instant createdAt) {}
|
||||
|
||||
// EnvironmentStatus.java
|
||||
package com.cameleer3.server.core.runtime;
|
||||
package com.cameleer.server.core.runtime;
|
||||
public enum EnvironmentStatus { ACTIVE, SUSPENDED }
|
||||
|
||||
// App.java
|
||||
package com.cameleer3.server.core.runtime;
|
||||
package com.cameleer.server.core.runtime;
|
||||
import java.time.Instant;
|
||||
import java.util.UUID;
|
||||
public record App(UUID id, UUID environmentId, String slug, String displayName, Instant createdAt) {}
|
||||
|
||||
// AppVersion.java
|
||||
package com.cameleer3.server.core.runtime;
|
||||
package com.cameleer.server.core.runtime;
|
||||
import java.time.Instant;
|
||||
import java.util.UUID;
|
||||
public record AppVersion(UUID id, UUID appId, int version, String jarPath, String jarChecksum,
|
||||
String jarFilename, Long jarSizeBytes, Instant uploadedAt) {}
|
||||
|
||||
// Deployment.java
|
||||
package com.cameleer3.server.core.runtime;
|
||||
package com.cameleer.server.core.runtime;
|
||||
import java.time.Instant;
|
||||
import java.util.UUID;
|
||||
public record Deployment(UUID id, UUID appId, UUID appVersionId, UUID environmentId,
|
||||
@@ -227,18 +227,18 @@ public record Deployment(UUID id, UUID appId, UUID appVersionId, UUID environmen
|
||||
}
|
||||
|
||||
// DeploymentStatus.java
|
||||
package com.cameleer3.server.core.runtime;
|
||||
package com.cameleer.server.core.runtime;
|
||||
public enum DeploymentStatus { STARTING, RUNNING, FAILED, STOPPED }
|
||||
|
||||
// RoutingMode.java
|
||||
package com.cameleer3.server.core.runtime;
|
||||
package com.cameleer.server.core.runtime;
|
||||
public enum RoutingMode { path, subdomain }
|
||||
```
|
||||
|
||||
- [x] **Step 2: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-core/src/main/java/com/cameleer3/server/core/runtime/
|
||||
git add cameleer-server-core/src/main/java/com/cameleer/server/core/runtime/
|
||||
git commit -m "feat: add runtime management domain records"
|
||||
```
|
||||
|
||||
@@ -253,7 +253,7 @@ git commit -m "feat: add runtime management domain records"
|
||||
|
||||
```java
|
||||
// EnvironmentRepository.java
|
||||
package com.cameleer3.server.core.runtime;
|
||||
package com.cameleer.server.core.runtime;
|
||||
import java.util.*;
|
||||
public interface EnvironmentRepository {
|
||||
List<Environment> findAll();
|
||||
@@ -266,7 +266,7 @@ public interface EnvironmentRepository {
|
||||
}
|
||||
|
||||
// AppRepository.java
|
||||
package com.cameleer3.server.core.runtime;
|
||||
package com.cameleer.server.core.runtime;
|
||||
import java.util.*;
|
||||
public interface AppRepository {
|
||||
List<App> findByEnvironmentId(UUID environmentId);
|
||||
@@ -277,7 +277,7 @@ public interface AppRepository {
|
||||
}
|
||||
|
||||
// AppVersionRepository.java
|
||||
package com.cameleer3.server.core.runtime;
|
||||
package com.cameleer.server.core.runtime;
|
||||
import java.util.*;
|
||||
public interface AppVersionRepository {
|
||||
List<AppVersion> findByAppId(UUID appId);
|
||||
@@ -287,7 +287,7 @@ public interface AppVersionRepository {
|
||||
}
|
||||
|
||||
// DeploymentRepository.java
|
||||
package com.cameleer3.server.core.runtime;
|
||||
package com.cameleer.server.core.runtime;
|
||||
import java.util.*;
|
||||
public interface DeploymentRepository {
|
||||
List<Deployment> findByAppId(UUID appId);
|
||||
@@ -305,7 +305,7 @@ public interface DeploymentRepository {
|
||||
|
||||
```java
|
||||
// RuntimeOrchestrator.java
|
||||
package com.cameleer3.server.core.runtime;
|
||||
package com.cameleer.server.core.runtime;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -319,7 +319,7 @@ public interface RuntimeOrchestrator {
|
||||
}
|
||||
|
||||
// ContainerRequest.java
|
||||
package com.cameleer3.server.core.runtime;
|
||||
package com.cameleer.server.core.runtime;
|
||||
import java.util.Map;
|
||||
public record ContainerRequest(
|
||||
String containerName,
|
||||
@@ -334,7 +334,7 @@ public record ContainerRequest(
|
||||
) {}
|
||||
|
||||
// ContainerStatus.java
|
||||
package com.cameleer3.server.core.runtime;
|
||||
package com.cameleer.server.core.runtime;
|
||||
public record ContainerStatus(String state, boolean running, int exitCode, String error) {
|
||||
public static ContainerStatus notFound() {
|
||||
return new ContainerStatus("not_found", false, -1, "Container not found");
|
||||
@@ -345,7 +345,7 @@ public record ContainerStatus(String state, boolean running, int exitCode, Strin
|
||||
- [x] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-core/src/main/java/com/cameleer3/server/core/runtime/
|
||||
git add cameleer-server-core/src/main/java/com/cameleer/server/core/runtime/
|
||||
git commit -m "feat: add runtime repository interfaces and RuntimeOrchestrator"
|
||||
```
|
||||
|
||||
@@ -359,7 +359,7 @@ git commit -m "feat: add runtime repository interfaces and RuntimeOrchestrator"
|
||||
- [x] **Step 1: Create EnvironmentService**
|
||||
|
||||
```java
|
||||
package com.cameleer3.server.core.runtime;
|
||||
package com.cameleer.server.core.runtime;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
@@ -395,7 +395,7 @@ public class EnvironmentService {
|
||||
- [x] **Step 2: Create AppService**
|
||||
|
||||
```java
|
||||
package com.cameleer3.server.core.runtime;
|
||||
package com.cameleer.server.core.runtime;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -478,7 +478,7 @@ public class AppService {
|
||||
- [x] **Step 3: Create DeploymentService**
|
||||
|
||||
```java
|
||||
package com.cameleer3.server.core.runtime;
|
||||
package com.cameleer.server.core.runtime;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -536,7 +536,7 @@ public class DeploymentService {
|
||||
- [x] **Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-core/src/main/java/com/cameleer3/server/core/runtime/
|
||||
git add cameleer-server-core/src/main/java/com/cameleer/server/core/runtime/
|
||||
git commit -m "feat: add EnvironmentService, AppService, DeploymentService"
|
||||
```
|
||||
|
||||
@@ -598,14 +598,14 @@ public class RuntimeBeanConfig {
|
||||
|
||||
- [x] **Step 3: Run tests**
|
||||
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer3-server && mvn test -pl cameleer3-server-app`
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer-server && mvn test -pl cameleer-server-app`
|
||||
Expected: PASS (Flyway applies V3 migration, context loads).
|
||||
|
||||
- [x] **Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-app/src/main/java/com/cameleer3/server/app/storage/Postgres*Repository.java
|
||||
git add cameleer3-server-app/src/main/java/com/cameleer3/server/app/config/RuntimeBeanConfig.java
|
||||
git add cameleer-server-app/src/main/java/com/cameleer/server/app/storage/Postgres*Repository.java
|
||||
git add cameleer-server-app/src/main/java/com/cameleer/server/app/config/RuntimeBeanConfig.java
|
||||
git commit -m "feat: implement PostgreSQL repositories for runtime management"
|
||||
```
|
||||
|
||||
@@ -614,16 +614,16 @@ git commit -m "feat: implement PostgreSQL repositories for runtime management"
|
||||
### Task 7: Docker Runtime Orchestrator
|
||||
|
||||
**Files:**
|
||||
- Create: `cameleer3-server-app/src/main/java/com/cameleer3/server/app/runtime/DockerRuntimeOrchestrator.java`
|
||||
- Create: `cameleer3-server-app/src/main/java/com/cameleer3/server/app/runtime/DisabledRuntimeOrchestrator.java`
|
||||
- Create: `cameleer3-server-app/src/main/java/com/cameleer3/server/app/runtime/RuntimeOrchestratorAutoConfig.java`
|
||||
- Create: `cameleer-server-app/src/main/java/com/cameleer/server/app/runtime/DockerRuntimeOrchestrator.java`
|
||||
- Create: `cameleer-server-app/src/main/java/com/cameleer/server/app/runtime/DisabledRuntimeOrchestrator.java`
|
||||
- Create: `cameleer-server-app/src/main/java/com/cameleer/server/app/runtime/RuntimeOrchestratorAutoConfig.java`
|
||||
|
||||
- [x] **Step 1: Implement DisabledRuntimeOrchestrator**
|
||||
|
||||
```java
|
||||
package com.cameleer3.server.app.runtime;
|
||||
package com.cameleer.server.app.runtime;
|
||||
|
||||
import com.cameleer3.server.core.runtime.*;
|
||||
import com.cameleer.server.core.runtime.*;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class DisabledRuntimeOrchestrator implements RuntimeOrchestrator {
|
||||
@@ -685,9 +685,9 @@ public String startContainer(ContainerRequest request) {
|
||||
- [x] **Step 3: Implement RuntimeOrchestratorAutoConfig**
|
||||
|
||||
```java
|
||||
package com.cameleer3.server.app.runtime;
|
||||
package com.cameleer.server.app.runtime;
|
||||
|
||||
import com.cameleer3.server.core.runtime.RuntimeOrchestrator;
|
||||
import com.cameleer.server.core.runtime.RuntimeOrchestrator;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -718,7 +718,7 @@ public class RuntimeOrchestratorAutoConfig {
|
||||
- [x] **Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-app/src/main/java/com/cameleer3/server/app/runtime/
|
||||
git add cameleer-server-app/src/main/java/com/cameleer/server/app/runtime/
|
||||
git commit -m "feat: implement DockerRuntimeOrchestrator with volume-mount JAR deployment"
|
||||
```
|
||||
|
||||
@@ -727,14 +727,14 @@ git commit -m "feat: implement DockerRuntimeOrchestrator with volume-mount JAR d
|
||||
### Task 8: DeploymentExecutor — Async Deployment Pipeline
|
||||
|
||||
**Files:**
|
||||
- Create: `cameleer3-server-app/src/main/java/com/cameleer3/server/app/runtime/DeploymentExecutor.java`
|
||||
- Create: `cameleer-server-app/src/main/java/com/cameleer/server/app/runtime/DeploymentExecutor.java`
|
||||
|
||||
- [x] **Step 1: Implement async deployment pipeline**
|
||||
|
||||
```java
|
||||
package com.cameleer3.server.app.runtime;
|
||||
package com.cameleer.server.app.runtime;
|
||||
|
||||
import com.cameleer3.server.core.runtime.*;
|
||||
import com.cameleer.server.core.runtime.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
@@ -841,7 +841,7 @@ public TaskExecutor deploymentTaskExecutor() {
|
||||
- [x] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-app/src/main/java/com/cameleer3/server/app/runtime/DeploymentExecutor.java
|
||||
git add cameleer-server-app/src/main/java/com/cameleer/server/app/runtime/DeploymentExecutor.java
|
||||
git commit -m "feat: implement async DeploymentExecutor pipeline"
|
||||
```
|
||||
|
||||
@@ -907,9 +907,9 @@ Add to `SecurityConfig.filterChain()`:
|
||||
- [x] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/EnvironmentAdminController.java
|
||||
git add cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/AppController.java
|
||||
git add cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/DeploymentController.java
|
||||
git add cameleer-server-app/src/main/java/com/cameleer/server/app/controller/EnvironmentAdminController.java
|
||||
git add cameleer-server-app/src/main/java/com/cameleer/server/app/controller/AppController.java
|
||||
git add cameleer-server-app/src/main/java/com/cameleer/server/app/controller/DeploymentController.java
|
||||
git commit -m "feat: add REST controllers for environment, app, and deployment management"
|
||||
```
|
||||
|
||||
@@ -918,7 +918,7 @@ git commit -m "feat: add REST controllers for environment, app, and deployment m
|
||||
### Task 10: Configuration and Application Properties
|
||||
|
||||
**Files:**
|
||||
- Modify: `cameleer3-server-app/src/main/resources/application.yml`
|
||||
- Modify: `cameleer-server-app/src/main/resources/application.yml`
|
||||
|
||||
- [x] **Step 1: Add runtime config properties**
|
||||
|
||||
@@ -939,13 +939,13 @@ cameleer:
|
||||
|
||||
- [x] **Step 2: Run full test suite**
|
||||
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer3-server && mvn clean verify`
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer-server && mvn clean verify`
|
||||
Expected: PASS.
|
||||
|
||||
- [x] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-app/src/main/resources/application.yml
|
||||
git add cameleer-server-app/src/main/resources/application.yml
|
||||
git commit -m "feat: add runtime management configuration properties"
|
||||
```
|
||||
|
||||
@@ -968,7 +968,7 @@ Test deployment creation (with `DisabledRuntimeOrchestrator` — verifies the de
|
||||
- [x] **Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add cameleer3-server-app/src/test/java/com/cameleer3/server/app/controller/
|
||||
git add cameleer-server-app/src/test/java/com/cameleer/server/app/controller/
|
||||
git commit -m "test: add integration tests for runtime management API"
|
||||
```
|
||||
|
||||
@@ -978,7 +978,7 @@ git commit -m "test: add integration tests for runtime management API"
|
||||
|
||||
- [x] **Step 1: Run full build**
|
||||
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer3-server && mvn clean verify`
|
||||
Run: `cd /c/Users/Hendrik/Documents/projects/cameleer-server && mvn clean verify`
|
||||
Expected: All tests PASS.
|
||||
|
||||
- [x] **Step 2: Verify schema applies cleanly**
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
**Repo:** `C:\Users\Hendrik\Documents\projects\cameleer-saas`
|
||||
|
||||
**Prerequisite:** Plans 1-3 must be implemented in cameleer3-server first.
|
||||
**Prerequisite:** Plans 1-3 must be implemented in cameleer-server first.
|
||||
|
||||
---
|
||||
|
||||
@@ -212,7 +212,7 @@ git commit -m "feat: remove migrated environment/app/deployment/runtime code fro
|
||||
|
||||
```sql
|
||||
-- V010__drop_migrated_tables.sql
|
||||
-- Drop tables that have been migrated to cameleer3-server
|
||||
-- Drop tables that have been migrated to cameleer-server
|
||||
|
||||
DROP TABLE IF EXISTS deployments CASCADE;
|
||||
DROP TABLE IF EXISTS apps CASCADE;
|
||||
@@ -242,7 +242,7 @@ group_add:
|
||||
- "0"
|
||||
```
|
||||
|
||||
The Docker socket mount now belongs to the `cameleer3-server` service instead.
|
||||
The Docker socket mount now belongs to the `cameleer-server` service instead.
|
||||
|
||||
- [ ] **Step 2: Remove docker-java dependency from pom.xml**
|
||||
|
||||
@@ -328,7 +328,7 @@ git commit -m "feat: expand ServerApiClient with license push and health check m
|
||||
|
||||
- [ ] **Step 1: Create integration contract document**
|
||||
|
||||
Create `docs/SAAS-INTEGRATION.md` in the cameleer3-server repo documenting:
|
||||
Create `docs/SAAS-INTEGRATION.md` in the cameleer-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`)
|
||||
@@ -339,7 +339,7 @@ Create `docs/SAAS-INTEGRATION.md` in the cameleer3-server repo documenting:
|
||||
- [ ] **Step 2: Commit**
|
||||
|
||||
```bash
|
||||
cd /c/Users/Hendrik/Documents/projects/cameleer3-server
|
||||
cd /c/Users/Hendrik/Documents/projects/cameleer-server
|
||||
git add docs/SAAS-INTEGRATION.md
|
||||
git commit -m "docs: add SaaS integration contract documentation"
|
||||
```
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
> **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:** Redesign the cameleer-saas platform from a read-only viewer into a vendor management plane that provisions per-tenant cameleer3-server instances, with vendor CRUD and customer self-service.
|
||||
**Goal:** Redesign the cameleer-saas platform from a read-only viewer into a vendor management plane that provisions per-tenant cameleer-server instances, with vendor CRUD and customer self-service.
|
||||
|
||||
**Architecture:** Two-persona split (vendor console at `/vendor/*`, tenant portal at `/tenant/*`). Pluggable `TenantProvisioner` interface with Docker implementation. Backend orchestrates provisioning + Logto + licensing in a single create-tenant flow. Frontend adapts sidebar/routes by persona.
|
||||
|
||||
@@ -410,13 +410,13 @@ Append to `application.yml`:
|
||||
```yaml
|
||||
cameleer:
|
||||
provisioning:
|
||||
server-image: ${CAMELEER_SERVER_IMAGE:gitea.siegeln.net/cameleer/cameleer3-server:latest}
|
||||
server-ui-image: ${CAMELEER_SERVER_UI_IMAGE:gitea.siegeln.net/cameleer/cameleer3-server-ui:latest}
|
||||
server-image: ${CAMELEER_SERVER_IMAGE:gitea.siegeln.net/cameleer/cameleer-server:latest}
|
||||
server-ui-image: ${CAMELEER_SERVER_UI_IMAGE:gitea.siegeln.net/cameleer/cameleer-server-ui:latest}
|
||||
network-name: ${CAMELEER_NETWORK:cameleer-saas_cameleer}
|
||||
traefik-network: ${CAMELEER_TRAEFIK_NETWORK:cameleer-traefik}
|
||||
public-host: ${PUBLIC_HOST:localhost}
|
||||
public-protocol: ${PUBLIC_PROTOCOL:https}
|
||||
datasource-url: ${CAMELEER_SERVER_DB_URL:jdbc:postgresql://postgres:5432/cameleer3}
|
||||
datasource-url: ${CAMELEER_SERVER_DB_URL:jdbc:postgresql://postgres:5432/cameleer}
|
||||
oidc-issuer-uri: ${PUBLIC_PROTOCOL:https}://${PUBLIC_HOST:localhost}/oidc
|
||||
oidc-jwk-set-uri: http://logto:3001/oidc/jwks
|
||||
cors-origins: ${PUBLIC_PROTOCOL:https}://${PUBLIC_HOST:localhost}
|
||||
@@ -1877,7 +1877,7 @@ import { LayoutDashboard, ShieldCheck, Server, Users, Settings, KeyRound, Buildi
|
||||
import { useAuth } from '../auth/useAuth';
|
||||
import { useScopes } from '../auth/useScopes';
|
||||
import { useOrgStore } from '../auth/useOrganization';
|
||||
import logo from '@cameleer/design-system/assets/cameleer3-logo.svg';
|
||||
import logo from '@cameleer/design-system/assets/cameleer-logo.svg';
|
||||
|
||||
export function Layout() {
|
||||
const navigate = useNavigate();
|
||||
@@ -2940,8 +2940,8 @@ This gives the SaaS container access to the Docker daemon for provisioning.
|
||||
Add to the `cameleer-saas` environment section:
|
||||
|
||||
```yaml
|
||||
CAMELEER_SERVER_IMAGE: gitea.siegeln.net/cameleer/cameleer3-server:${VERSION:-latest}
|
||||
CAMELEER_SERVER_UI_IMAGE: gitea.siegeln.net/cameleer/cameleer3-server-ui:${VERSION:-latest}
|
||||
CAMELEER_SERVER_IMAGE: gitea.siegeln.net/cameleer/cameleer-server:${VERSION:-latest}
|
||||
CAMELEER_SERVER_UI_IMAGE: gitea.siegeln.net/cameleer/cameleer-server-ui:${VERSION:-latest}
|
||||
CAMELEER_NETWORK: cameleer-saas_cameleer
|
||||
CAMELEER_TRAEFIK_NETWORK: cameleer-traefik
|
||||
```
|
||||
|
||||
@@ -581,7 +581,7 @@ In `ui/sign-in/src/SignInPage.tsx`, find the logo text (line ~61):
|
||||
// BEFORE:
|
||||
<div className={styles.logo}>
|
||||
<img src={cameleerLogo} alt="" className={styles.logoImg} />
|
||||
cameleer3
|
||||
cameleer
|
||||
</div>
|
||||
|
||||
// AFTER:
|
||||
|
||||
210
docs/superpowers/plans/2026-04-10-fleet-health-plan.md
Normal file
210
docs/superpowers/plans/2026-04-10-fleet-health-plan.md
Normal file
@@ -0,0 +1,210 @@
|
||||
# Fleet Health at a Glance 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:** Add agent count, environment count, and agent limit columns to the vendor tenant list so the vendor can see fleet utilization at a glance.
|
||||
|
||||
**Architecture:** Extend the existing `VendorTenantSummary` record with three int fields. The list endpoint fetches counts from each active tenant's server via existing M2M API methods (`getAgentCount`, `getEnvironmentCount`), parallelized with `CompletableFuture`. Frontend adds two columns (Agents, Envs) to the DataTable.
|
||||
|
||||
**Tech Stack:** Java 21, Spring Boot, CompletableFuture, React, TypeScript, @cameleer/design-system DataTable
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Extend backend — VendorTenantSummary + parallel fetch
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/main/java/net/siegeln/cameleer/saas/vendor/VendorTenantController.java`
|
||||
|
||||
- [ ] **Step 1: Extend the VendorTenantSummary record**
|
||||
|
||||
In `VendorTenantController.java`, replace the record at lines 39-48:
|
||||
|
||||
```java
|
||||
public record VendorTenantSummary(
|
||||
UUID id,
|
||||
String name,
|
||||
String slug,
|
||||
String tier,
|
||||
String status,
|
||||
String serverState,
|
||||
String licenseExpiry,
|
||||
String provisionError,
|
||||
int agentCount,
|
||||
int environmentCount,
|
||||
int agentLimit
|
||||
) {}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Update the listAll() endpoint to fetch counts in parallel**
|
||||
|
||||
Replace the `listAll()` method at lines 60-77:
|
||||
|
||||
```java
|
||||
@GetMapping
|
||||
public ResponseEntity<List<VendorTenantSummary>> listAll() {
|
||||
var tenants = vendorTenantService.listAll();
|
||||
|
||||
// Parallel health fetch for active tenants
|
||||
var futures = tenants.stream().map(tenant -> java.util.concurrent.CompletableFuture.supplyAsync(() -> {
|
||||
ServerStatus status = vendorTenantService.getServerStatus(tenant);
|
||||
String licenseExpiry = vendorTenantService
|
||||
.getLicenseForTenant(tenant.getId())
|
||||
.map(l -> l.getExpiresAt() != null ? l.getExpiresAt().toString() : null)
|
||||
.orElse(null);
|
||||
|
||||
int agentCount = 0;
|
||||
int environmentCount = 0;
|
||||
int agentLimit = -1;
|
||||
|
||||
String endpoint = tenant.getServerEndpoint();
|
||||
boolean isActive = "ACTIVE".equals(tenant.getStatus().name());
|
||||
if (isActive && endpoint != null && !endpoint.isBlank() && "RUNNING".equals(status.state().name())) {
|
||||
var serverApi = vendorTenantService.getServerApiClient();
|
||||
agentCount = serverApi.getAgentCount(endpoint);
|
||||
environmentCount = serverApi.getEnvironmentCount(endpoint);
|
||||
}
|
||||
|
||||
var license = vendorTenantService.getLicenseForTenant(tenant.getId());
|
||||
if (license.isPresent() && license.get().getLimits() != null) {
|
||||
var limits = license.get().getLimits();
|
||||
if (limits.containsKey("agents")) {
|
||||
agentLimit = ((Number) limits.get("agents")).intValue();
|
||||
}
|
||||
}
|
||||
|
||||
return new VendorTenantSummary(
|
||||
tenant.getId(), tenant.getName(), tenant.getSlug(),
|
||||
tenant.getTier().name(), tenant.getStatus().name(),
|
||||
status.state().name(), licenseExpiry, tenant.getProvisionError(),
|
||||
agentCount, environmentCount, agentLimit
|
||||
);
|
||||
})).toList();
|
||||
|
||||
List<VendorTenantSummary> summaries = futures.stream()
|
||||
.map(java.util.concurrent.CompletableFuture::join)
|
||||
.toList();
|
||||
|
||||
return ResponseEntity.ok(summaries);
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Expose ServerApiClient from VendorTenantService**
|
||||
|
||||
Add a getter in `src/main/java/net/siegeln/cameleer/saas/vendor/VendorTenantService.java`:
|
||||
|
||||
```java
|
||||
public ServerApiClient getServerApiClient() {
|
||||
return serverApiClient;
|
||||
}
|
||||
```
|
||||
|
||||
(The `serverApiClient` field already exists in VendorTenantService — check around line 30.)
|
||||
|
||||
- [ ] **Step 4: Verify compilation**
|
||||
|
||||
Run: `./mvnw compile -pl . -q`
|
||||
Expected: BUILD SUCCESS
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add src/main/java/net/siegeln/cameleer/saas/vendor/VendorTenantController.java \
|
||||
src/main/java/net/siegeln/cameleer/saas/vendor/VendorTenantService.java
|
||||
git commit -m "feat: add agent/env counts to vendor tenant list endpoint"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 2: Update frontend types and columns
|
||||
|
||||
**Files:**
|
||||
- Modify: `ui/src/types/api.ts`
|
||||
- Modify: `ui/src/pages/vendor/VendorTenantsPage.tsx`
|
||||
|
||||
- [ ] **Step 1: Add fields to VendorTenantSummary TypeScript type**
|
||||
|
||||
In `ui/src/types/api.ts`, update the `VendorTenantSummary` interface:
|
||||
|
||||
```typescript
|
||||
export interface VendorTenantSummary {
|
||||
id: string;
|
||||
name: string;
|
||||
slug: string;
|
||||
tier: string;
|
||||
status: string;
|
||||
serverState: string;
|
||||
licenseExpiry: string | null;
|
||||
provisionError: string | null;
|
||||
agentCount: number;
|
||||
environmentCount: number;
|
||||
agentLimit: number;
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Add Agents and Envs columns to VendorTenantsPage**
|
||||
|
||||
In `ui/src/pages/vendor/VendorTenantsPage.tsx`, add a helper function after `statusColor`:
|
||||
|
||||
```typescript
|
||||
function formatUsage(used: number, limit: number): string {
|
||||
return limit < 0 ? `${used} / ∞` : `${used} / ${limit}`;
|
||||
}
|
||||
```
|
||||
|
||||
Then add two column entries in the `columns` array, after the `serverState` column (after line 54) and before the `licenseExpiry` column:
|
||||
|
||||
```typescript
|
||||
{
|
||||
key: 'agentCount',
|
||||
header: 'Agents',
|
||||
render: (_v, row) => (
|
||||
<span style={{ fontFamily: 'monospace', fontSize: '0.875rem' }}>
|
||||
{formatUsage(row.agentCount, row.agentLimit)}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'environmentCount',
|
||||
header: 'Envs',
|
||||
render: (_v, row) => (
|
||||
<span style={{ fontFamily: 'monospace', fontSize: '0.875rem' }}>
|
||||
{row.environmentCount}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Build the UI**
|
||||
|
||||
Run: `cd ui && npm run build`
|
||||
Expected: Build succeeds with no errors.
|
||||
|
||||
- [ ] **Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add ui/src/types/api.ts ui/src/pages/vendor/VendorTenantsPage.tsx
|
||||
git commit -m "feat: show agent/env counts in vendor tenant list"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 3: Verify end-to-end
|
||||
|
||||
- [ ] **Step 1: Run backend tests**
|
||||
|
||||
Run: `./mvnw test -pl . -q`
|
||||
Expected: All tests pass. (Existing tests use mocks, the new parallel fetch doesn't break them since it only affects the controller's list mapping.)
|
||||
|
||||
- [ ] **Step 2: Verify in browser**
|
||||
|
||||
Navigate to the vendor tenant list. Confirm:
|
||||
- "Agents" column shows "0 / ∞" (or actual count if agents are connected)
|
||||
- "Envs" column shows "1" (or actual count)
|
||||
- PROVISIONING/SUSPENDED tenants show "0" for both
|
||||
- 30s auto-refresh still works
|
||||
|
||||
- [ ] **Step 3: Final commit and push**
|
||||
|
||||
```bash
|
||||
git push
|
||||
```
|
||||
@@ -1572,8 +1572,8 @@ VENDOR_PASS=${VENDOR_PASS:-}
|
||||
DOCKER_SOCKET=${DOCKER_SOCKET}
|
||||
|
||||
# Provisioning images
|
||||
CAMELEER_SAAS_PROVISIONING_SERVERIMAGE=${REGISTRY}/cameleer3-server:${VERSION}
|
||||
CAMELEER_SAAS_PROVISIONING_SERVERUIIMAGE=${REGISTRY}/cameleer3-server-ui:${VERSION}
|
||||
CAMELEER_SAAS_PROVISIONING_SERVERIMAGE=${REGISTRY}/cameleer-server:${VERSION}
|
||||
CAMELEER_SAAS_PROVISIONING_SERVERUIIMAGE=${REGISTRY}/cameleer-server-ui:${VERSION}
|
||||
EOF
|
||||
|
||||
log_info "Generated .env"
|
||||
@@ -1793,8 +1793,8 @@ EOF
|
||||
CAMELEER_SAAS_PROVISIONING_PUBLICHOST: ${PUBLIC_HOST:-localhost}
|
||||
CAMELEER_SAAS_PROVISIONING_NETWORKNAME: ${COMPOSE_PROJECT_NAME:-cameleer-saas}_cameleer
|
||||
CAMELEER_SAAS_PROVISIONING_TRAEFIKNETWORK: cameleer-traefik
|
||||
CAMELEER_SAAS_PROVISIONING_SERVERIMAGE: ${CAMELEER_SAAS_PROVISIONING_SERVERIMAGE:-gitea.siegeln.net/cameleer/cameleer3-server:latest}
|
||||
CAMELEER_SAAS_PROVISIONING_SERVERUIIMAGE: ${CAMELEER_SAAS_PROVISIONING_SERVERUIIMAGE:-gitea.siegeln.net/cameleer/cameleer3-server-ui:latest}
|
||||
CAMELEER_SAAS_PROVISIONING_SERVERIMAGE: ${CAMELEER_SAAS_PROVISIONING_SERVERIMAGE:-gitea.siegeln.net/cameleer/cameleer-server:latest}
|
||||
CAMELEER_SAAS_PROVISIONING_SERVERUIIMAGE: ${CAMELEER_SAAS_PROVISIONING_SERVERUIIMAGE:-gitea.siegeln.net/cameleer/cameleer-server-ui:latest}
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.saas.rule=PathPrefix(`/platform`)
|
||||
@@ -2109,7 +2109,7 @@ EOF
|
||||
| `logto` | OIDC identity provider + bootstrap |
|
||||
| `cameleer-saas` | SaaS platform (Spring Boot + React) |
|
||||
|
||||
Per-tenant `cameleer3-server` and `cameleer3-server-ui` containers are provisioned dynamically when tenants are created.
|
||||
Per-tenant `cameleer-server` and `cameleer-server-ui` containers are provisioned dynamically when tenants are created.
|
||||
|
||||
## Networking
|
||||
|
||||
@@ -2656,7 +2656,7 @@ Tasks 8-16 ────── can run in parallel with Phase 1
|
||||
|
||||
## Follow-up (out of scope)
|
||||
|
||||
- Bake `docker/server-ui-entrypoint.sh` into the `cameleer3-server-ui` image (separate repo)
|
||||
- Bake `docker/server-ui-entrypoint.sh` into the `cameleer-server-ui` image (separate repo)
|
||||
- Set up `install.cameleer.io` distribution endpoint
|
||||
- Create release automation (tag → publish installer scripts to distribution endpoint)
|
||||
- Add `docker-compose.dev.yml` overlay generation for the installer's expert mode
|
||||
|
||||
@@ -87,7 +87,7 @@ import java.sql.Statement;
|
||||
|
||||
/**
|
||||
* Creates and drops per-tenant PostgreSQL users and schemas
|
||||
* on the shared cameleer3 database for DB-level tenant isolation.
|
||||
* on the shared cameleer database for DB-level tenant isolation.
|
||||
*/
|
||||
@Service
|
||||
public class TenantDatabaseService {
|
||||
|
||||
Reference in New Issue
Block a user