Commit Graph

293 Commits

Author SHA1 Message Date
hsiegeln
5ed33807d8 fix: use /api/v1/health for server health checks (not /actuator/health)
Some checks failed
CI / build (push) Successful in 49s
CI / docker (push) Successful in 30s
SonarQube Analysis / sonarqube (push) Failing after 1m24s
The server's /actuator/health requires auth. The public health endpoint
is /api/v1/health (same as compose-managed server's Docker HEALTHCHECK).
Also increased health check retries/timeout and added startPeriod.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 23:43:46 +02:00
hsiegeln
00476c974f fix: vendor scoping, sidebar visibility, and landing redirect
All checks were successful
CI / build (push) Successful in 50s
CI / docker (push) Successful in 41s
- OrgResolver merges global + org-scoped token scopes so vendor's
  platform:admin (from global saas-vendor role) is always visible
- LandingRedirect waits for scopes to load before redirecting
  (prevents premature redirect to server dashboard)
- Layout hides tenant portal sidebar items when vendor is on
  /vendor/* routes; shows them when navigating to tenant context

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 23:39:12 +02:00
hsiegeln
c674785c82 fix: merge global + org-scoped token scopes in OrgResolver
All checks were successful
CI / build (push) Successful in 50s
CI / docker (push) Successful in 40s
Vendor's platform:admin scope comes from a global Logto role, which is
only present in the non-org-scoped token. OrgResolver now fetches both
the global token and the org-scoped token, merging their scopes. This
ensures vendor users see platform:admin and land on the vendor console.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 23:33:30 +02:00
hsiegeln
4087ce8f29 fix: provisioned server containers — strip-prefix, Docker socket, env
All checks were successful
CI / build (push) Successful in 1m14s
CI / docker (push) Successful in 34s
- Add Traefik strip-prefix middleware so /t/{slug}/api -> /api on server
- Add priority to routers (server API=10, UI=5) to prevent conflicts
- Mount Docker socket + group_add in server containers for app deployment
- Add JAR storage, Docker network, volume env vars for runtime orchestrator
- Use HashMap for labels (>10 entries exceeds Map.of limit)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 23:26:48 +02:00
hsiegeln
39c3b39711 feat: role-based sidebar visibility and landing redirect
All checks were successful
CI / build (push) Successful in 51s
CI / docker (push) Successful in 42s
- Vendor (platform:admin): sees only TENANTS in sidebar
- Tenant admin (tenant:manage): sees Dashboard, License, OIDC, Team, Settings
- Regular user (operator/viewer): redirected to server dashboard directly
- LandingRedirect checks scopes in priority order: vendor > admin > server

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 23:24:22 +02:00
hsiegeln
cdd495d985 ci: exclude new integration tests from CI (no Testcontainers in CI)
All checks were successful
CI / build (push) Successful in 50s
CI / docker (push) Successful in 33s
VendorTenantControllerTest and TenantPortalControllerTest use
@SpringBootTest + Testcontainers PostgreSQL, same as the existing
controller tests that are already excluded.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 23:11:45 +02:00
hsiegeln
17fbe73e60 test: add 25 tests for vendor + portal services and controllers
Some checks failed
CI / build (push) Failing after 1m16s
CI / docker (push) Has been skipped
VendorTenantServiceTest (8): create/provision, suspend, delete, renew
VendorTenantControllerTest (7): CRUD, auth, conflict handling
TenantPortalServiceTest (5): dashboard, license, settings
TenantPortalControllerTest (5): dashboard, license, settings, auth

Fix TenantIsolationInterceptor bugs found by tests:
- org_id resolution now runs before portal path check
- path matching uses URI minus context path (not getServletPath)
- portal path returns 403 sendError instead of empty 200

Total: 50 tests, 0 failures.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 23:08:47 +02:00
hsiegeln
faac0048c3 fix: add missing server env vars to DockerTenantProvisioner
All checks were successful
CI / build (push) Successful in 50s
CI / docker (push) Successful in 43s
Adds CAMELEER_AUTH_TOKEN, CAMELEER_JWT_SECRET, CAMELEER_OIDC_AUDIENCE,
CLICKHOUSE_URL to provisioned server containers. Also passes PUBLIC_HOST
and PUBLIC_PROTOCOL to SaaS container in dev overlay so provisioner
resolves the correct hostname instead of defaulting to localhost.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 22:53:21 +02:00
hsiegeln
e6f2f17fa1 fix: use correct tier enum values (LOW/MID/HIGH/BUSINESS) in create form
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 22:39:23 +02:00
hsiegeln
28d044efbc fix: vendor user now lands on /vendor/tenants after login
LandingRedirect component checks scopes — platform:admin goes to
vendor console, others go to tenant dashboard.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 22:37:28 +02:00
hsiegeln
6a81053d37 feat: integrate vendor seed into bootstrap with VENDOR_SEED_ENABLED switch
All checks were successful
CI / build (push) Successful in 1m13s
CI / docker (push) Successful in 49s
Phase 12 in logto-bootstrap.sh creates saas-vendor global role + vendor
user when VENDOR_SEED_ENABLED=true. Enabled by default in dev overlay.
Also restores GlobalFilterProvider + CommandPaletteProvider (required by
DS TopBar internally).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 22:30:06 +02:00
hsiegeln
fd41a056eb feat: Docker socket mount for tenant provisioning
Add Docker socket volume, group_add: ["0"], and provisioning env vars
(CAMELEER_SERVER_IMAGE, CAMELEER_SERVER_UI_IMAGE, CAMELEER_NETWORK,
CAMELEER_TRAEFIK_NETWORK) to the cameleer-saas service in docker-compose.dev.yml.
2026-04-09 22:30:06 +02:00
hsiegeln
9ecaf22f09 feat: tenant portal — all 5 pages (dashboard, license, OIDC, team, settings)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 22:30:06 +02:00
hsiegeln
d2f6b02a5f feat: vendor console — tenant list, create wizard, detail page
Implements Task 9: shared components (ServerStatusBadge, UsageIndicator,
platform.module.css, tierColor utility) and full vendor console pages
(VendorTenantsPage, CreateTenantPage, TenantDetailPage). Build passes cleanly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 22:30:06 +02:00
hsiegeln
bf3aa57274 feat: restructure frontend routes — vendor/tenant persona split
Splits the flat 3-page UI into /vendor/* (platform:admin) and /tenant/*
(all authenticated users) route trees, with stub pages, new API hooks,
updated Layout with persona-aware sidebar, and SpaController forwarding.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 22:29:59 +02:00
hsiegeln
e56e3fca8a feat: tenant portal API (dashboard, license, OIDC, team, settings)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 22:29:01 +02:00
hsiegeln
127834ce4d feat: vendor tenant API with provisioning, suspend, delete
Adds VendorTenantService orchestrating full tenant lifecycle (create,
provision, license push, activate, suspend, delete, renew license),
VendorTenantController at /api/vendor/tenants with platform:admin guard,
LicenseResponse.from() factory, SecurityConfig vendor/tenant path rules,
and TenantIsolationInterceptor bypasses for vendor and tenant portal paths.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 22:29:01 +02:00
hsiegeln
6bdb02ff5a feat: add per-tenant health, OIDC, team methods to API clients
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 22:29:01 +02:00
hsiegeln
96a5b1d9f1 feat: implement DockerTenantProvisioner with container lifecycle
Replace stub with full Docker implementation using docker-java. Manages
per-tenant server and UI containers with Traefik labels, health checks,
image pull, network attachment, and full lifecycle (provision/start/stop/remove/status).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 22:29:01 +02:00
hsiegeln
771e9d1081 feat: add TenantProvisioner interface with auto-detection
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 22:29:01 +02:00
hsiegeln
ebba021448 feat: add provisioning fields to tenants + license revoke
Adds server_endpoint and provision_error columns to tenants table (V011 migration),
updates TenantEntity and TenantResponse with new fields and a from() factory,
adds revokeLicense() to LicenseService, and updates TenantController to use the factory.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 22:29:01 +02:00
hsiegeln
81d570fd63 docs: add platform redesign implementation plan (12 tasks)
Backend: TenantProvisioner interface, DockerTenantProvisioner,
vendor API (create/provision/suspend/delete), tenant portal API
(dashboard/license/OIDC/team/settings). Frontend: route restructure
(/vendor/*, /tenant/*), persona-aware Layout, 8 new pages.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 22:29:01 +02:00
hsiegeln
7b92de4017 docs: add platform redesign spec with user stories
Redesign SaaS platform from read-only viewer into vendor management
plane with tenant provisioning, license management, and customer
self-service. Two personas (vendor/customer), pluggable provisioning
interface (Docker first, K8s later), per-tenant server instances.

User stories tracked as Gitea issues #40-#51. Closes #37.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 22:29:01 +02:00
0ba896ada4 Merge pull request 'SaaS platform UX polish: layout, navigation, error handling' (#39) from feature/saas-ux-polish into main
All checks were successful
CI / build (push) Successful in 53s
CI / docker (push) Successful in 11s
Reviewed-on: #39
2026-04-09 19:56:24 +02:00
hsiegeln
af7abc3eac fix: add confirmation dialog before tenant context switch
All checks were successful
CI / build (push) Successful in 1m18s
CI / build (pull_request) Successful in 1m19s
CI / docker (pull_request) Has been skipped
CI / docker (push) Successful in 1m1s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 19:51:59 +02:00
hsiegeln
ce1655bba6 fix: add error states to OrgResolver, DashboardPage, AdminTenantsPage
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 19:51:28 +02:00
hsiegeln
798ec4850d fix: replace raw button with DS Button, add token copy-to-clipboard
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 19:51:03 +02:00
hsiegeln
7d4126ad4e fix: unify tier color mapping, fix feature badge colors
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 19:50:28 +02:00
hsiegeln
e3d9a3bd18 fix: sidebar active state, breadcrumbs, collapse, username fallback, lucide icons
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 19:49:42 +02:00
hsiegeln
7c7d574aa7 fix: replace hardcoded text-white with DS variables, fix label/value layout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 19:49:32 +02:00
hsiegeln
f9b1628e14 fix: add password visibility toggle and fix branding to 'Cameleer'
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 19:49:14 +02:00
hsiegeln
e84e53f835 Add SaaS platform UX polish implementation plan (8 tasks)
Detailed step-by-step plan covering layout fixes (label/value collision,
DS variable adoption), header/navigation (sidebar active state,
breadcrumbs, collapse), error handling, DS component adoption, sign-in
improvements, and polish (tier colors, badges, confirmations).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 19:46:44 +02:00
hsiegeln
1133763520 Add SaaS platform UX polish design spec with audit findings
Playwright audit (22 screenshots) + source code audit covering all
platform pages. Spec defines 4 batches: layout fixes (label/value
collision, hardcoded colors), header/navigation (hide server controls,
sidebar active state), error handling & components (DS adoption,
copy-to-clipboard, error states), and polish (tier colors, badges).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 19:39:33 +02:00
hsiegeln
5c4a84e64c fix: platform label/value spacing and neutral license badge colors
Disabled features on the license page now show 'Not included' with a
neutral (auto) badge color instead of 'Disabled' in error red, which
looked like an actionable error rather than a plan tier indicator.

Label/value spacing on DashboardPage already used flex justify-between
correctly — no change needed there.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 18:46:09 +02:00
hsiegeln
538591989c docs: mark Plan 3 (runtime management port) as completed
All checks were successful
CI / build (push) Successful in 1m25s
CI / docker (push) Successful in 11s
Verified 2026-04-09: all runtime management fully ported to
cameleer3-server with enhancements beyond the original plan.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 08:58:15 +02:00
hsiegeln
63e6c6b1b5 docs: update CLAUDE.md with key classes, network topology, and runtime env vars
All checks were successful
CI / build (push) Successful in 1m18s
CI / docker (push) Successful in 19s
SonarQube Analysis / sonarqube (push) Successful in 1m12s
Add key class locations for Java backend and React frontend, document
cameleer-traefik network topology with DNS alias, add server runtime
env vars table, update deployment pipeline to 7-stage flow, add
database migration reference.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 23:11:03 +02:00
hsiegeln
4a7351d48e fix: add cameleer-traefik network so deployed apps can reach server
All checks were successful
CI / build (push) Successful in 53s
CI / docker (push) Successful in 10s
Deployed app containers are put on the cameleer-traefik network by the
orchestrator, but the server and Traefik were only on the compose-internal
network. This caused UnresolvedAddressException when apps tried to connect
to cameleer3-server:8081 for agent registration and SSE.

- Add cameleer-traefik network with fixed name (no compose project prefix)
- Attach server to cameleer-traefik with DNS alias "cameleer3-server"
- Attach Traefik to cameleer-traefik for routing to deployed apps
- Add dev overrides for Docker orchestration (socket, volumes, env vars)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 22:37:51 +02:00
hsiegeln
1d6c0cf451 docs: update documentation for Docker orchestration and env var rename
All checks were successful
CI / build (push) Successful in 1m0s
CI / docker (push) Successful in 18s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 22:09:19 +02:00
hsiegeln
cc792ae336 refactor: rename CAMELEER_EXPORT_ENDPOINT to CAMELEER_SERVER_URL in runtime-base
Some checks failed
CI / build (push) Successful in 1m7s
CI / docker (push) Has been cancelled
Standardize env var naming. The agent reads CAMELEER_SERVER_URL
to configure -Dcameleer.export.endpoint.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 22:06:48 +02:00
hsiegeln
bb8c68a5ca feat: seed claim mapping rules in bootstrap after OIDC config
All checks were successful
CI / build (push) Successful in 53s
CI / docker (push) Successful in 14s
After configuring the server's OIDC settings, the bootstrap now seeds
claim mapping rules so Logto roles (server:admin, server:operator) map
to server RBAC roles (ADMIN, OPERATOR) automatically. Rules are
idempotent — existing mappings are checked by matchValue before creating.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 12:21:28 +02:00
hsiegeln
cfc7842e18 ci: retry build (transient npm network error)
All checks were successful
CI / build (push) Successful in 49s
CI / docker (push) Successful in 1m16s
2026-04-08 08:56:44 +02:00
hsiegeln
3fa062b92c docs: add architecture review spec and implementation plans
Some checks failed
CI / build (push) Failing after 25s
CI / docker (push) Has been skipped
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 08:53:22 +02:00
hsiegeln
5938643632 feat: strip SaaS UI to vendor management dashboard
- Delete EnvironmentsPage, EnvironmentDetailPage, AppDetailPage
- Delete EnvironmentTree and DeploymentStatusBadge components
- Simplify DashboardPage to show tenant info, license status, server link
- Remove environment/app/deployment routes from router
- Remove environment section from sidebar, keep dashboard/license/platform
- Strip API hooks to tenant/license/me only
- Remove environment/app/deployment/observability types

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 00:03:01 +02:00
hsiegeln
de5821dddb feat: remove Docker socket dependency from SaaS layer
- Remove docker-java-core and docker-java-transport-zerodep from pom.xml
- Remove Docker socket mount, group_add, jardata volume from docker-compose.yml
- Remove CAMELEER_DOCKER_NETWORK and CLICKHOUSE_URL env vars from SaaS service
- Remove jardata volume definition

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 00:01:15 +02:00
hsiegeln
bad78e26a1 feat: add migration to drop migrated tables from SaaS database
- V010: drop deployments, apps, environments, api_keys tables
- Tables have been migrated to cameleer3-server

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 00:00:32 +02:00
hsiegeln
c254fbf723 feat: remove migrated environment/app/deployment/runtime code from SaaS
- Delete environment/, app/, deployment/, runtime/ packages (source + tests)
- Delete apikey/ package (tied to environments, table will be dropped)
- Strip AsyncConfig to empty @EnableAsync (no more deploymentExecutor bean)
- Remove EnvironmentService dependency from TenantService
- Remove environment/app isolation from TenantIsolationInterceptor
- Remove environment seeding from BootstrapDataSeeder
- Refactor ServerApiClient to use LogtoConfig instead of RuntimeConfig
- Add server-endpoint property to LogtoConfig (was in RuntimeConfig)
- Remove runtime config section and multipart config from application.yml

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 23:59:53 +02:00
hsiegeln
160a989f9f feat: remove all ClickHouse dependencies from SaaS layer
- Delete log/ package (ClickHouseConfig, ContainerLogService, LogController)
- Delete observability/ package (AgentStatusService, AgentStatusController)
- Remove clickhouse-jdbc dependency from pom.xml
- Remove cameleer.clickhouse config section from application.yml
- Delete associated test files

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 23:56:21 +02:00
hsiegeln
30aaacb5b5 fix: correct protocol version header, disable SQL logging, document deployment pipeline
All checks were successful
CI / build (push) Successful in 1m9s
CI / docker (push) Successful in 1m43s
SonarQube Analysis / sonarqube (push) Successful in 1m20s
- ServerApiClient: use X-Cameleer-Protocol-Version: 1 (server expects "1", not "2")
- Disable Hibernate show-sql in dev profile (too verbose)
- CLAUDE.md: document deployment pipeline architecture, M2M server role in bootstrap,
  runtime-base image in CI

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 18:58:27 +02:00
hsiegeln
617785baa7 fix: use full registry path for runtime base image default
All checks were successful
CI / build (push) Successful in 50s
CI / docker (push) Successful in 35s
The default cameleer-runtime-base:latest has no registry prefix, so
Docker can't pull it. Use the full gitea.siegeln.net/cameleer/ path.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 18:23:26 +02:00
hsiegeln
f14affcc1e fix: verify Management API readiness before proceeding in bootstrap
All checks were successful
CI / build (push) Successful in 48s
CI / docker (push) Successful in 14s
Logto's OIDC endpoint may respond before the Management API is fully
initialized. Add a retry loop that checks GET /api/roles returns valid
JSON before making any API calls. Fixes intermittent bootstrap failure
on cold starts with 'Cannot index string with string "name"'.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 18:18:08 +02:00