The compose volume `jars` gets created as `<project>_jars` by Docker
Compose, but JARDOCKERVOLUME tells the server to mount `cameleer-jars`
on deployed app containers. These are different Docker volumes, so
the app JAR was never visible inside the app container — causing
ClassNotFoundException on startup.
Fix: add `name: cameleer-jars` to the volume definition so both the
server and deployed app containers share the same named volume.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The @Lazy self-proxy pattern requires a non-null reference in tests.
Construct the instance then re-create with itself as the self param.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add missing runtimeBaseImage arg to ProvisioningProperties constructor
calls in tests. Also add missing self-proxy arg to VendorTenantService
constructor (pre-existing from async provisioning commit).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CAMELEER_SERVER_RUNTIME_BASEIMAGE was never set on provisioned
per-tenant server containers, causing them to fall back to the
server's hardcoded default. Added CAMELEER_SAAS_PROVISIONING_RUNTIMEBASEIMAGE
as a configurable property that gets forwarded during provisioning.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Async on provisionAsync() was bypassed because all call sites were
internal (this.provisionAsync), skipping the Spring proxy. Inject self
via @Lazy to route through the proxy so provisioning runs in a
background thread and the API returns immediately.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Windows Docker Compose uses ; not : as the path separator in COMPOSE_FILE.
The colon was being interpreted as part of the filename, causing CreateFile errors.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace inline heredoc compose generation with static template files.
Templates are copied to the install dir and composed via COMPOSE_FILE in .env.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reference .env file documenting all configuration variables across both
deployment modes, with section headers for compose assembly, public access,
credentials, TLS, Docker, provisioning, and monitoring.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Optional compose overlays: TLS overlay mounts user-supplied certs into
traefik, monitoring overlay replaces the noop bridge with an external
Docker network for Prometheus scraping.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Standalone mode: server + server-ui services with postgres image override
to stock postgres:16-alpine. Includes traefik-dynamic.yml for default TLS
certificate store configuration.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Logto identity provider and cameleer-saas management plane services.
Includes Traefik labels, CORS config, bootstrap healthcheck, and all
provisioning env vars parameterized from .env.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Docker compose templates defaulted to admin/admin when .env was missing.
Now uses :? to fail with a clear error instead of silently using weak creds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
The log appender JAR was missing from the cameleer-runtime-base Docker
image, causing agent log forwarding to silently fail with "No supported
logging framework found, log forwarding disabled". This meant only
container stdout logs (source=container) were captured — no application
or agent logs reached ClickHouse.
CI now downloads the appender JAR from the Maven registry alongside the
agent JAR, and the Dockerfile COPYs it to /app/cameleer3-log-appender.jar
where the server's Docker entrypoint expects it (-Dloader.path for
Spring Boot, -cp for plain Java).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Installers now use `--pull always --force-recreate` on `docker compose up`
to ensure fresh images are used on every install/reinstall, preventing
stale containers from missing schema changes like db_password.
Fix VendorTenantServiceTest to expect two repository saves in provisioning
tests (one for dbPassword, one for final status).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Constructor gained an 11th parameter (TenantDatabaseService) but the
test was not updated, breaking CI compilation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- TenantDatabaseService added to key classes
- TenantDataCleanupService now ClickHouse-only
- Per-tenant JDBC URL with currentSchema/ApplicationName in env vars table
- Provisioning flow updated with DB creation step
- Delete flow updated with schema+user drop
- Database migrations section reflects consolidated V001 baseline
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace 14 incremental migrations (V001-V015) with a single V001__init.sql
representing the final schema. Tables that were created and later dropped
(environments, api_keys, apps, deployments) are excluded.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
TenantDataCleanupService now handles only ClickHouse GDPR erasure;
the dropPostgresSchema private method is removed and the public method
renamed cleanupClickHouse(). VendorTenantService updated accordingly
with the TODO comment removed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Inject TenantDatabaseService; call createTenantDatabase() at the start
of provisionAsync() (stores generated password on TenantEntity), and
dropTenantDatabase() in delete() before GDPR data erasure.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Per-tenant PG users and schemas for DB-level data isolation.
Each tenant server gets its own credentials and currentSchema/ApplicationName
JDBC parameters, aligned with server team's commit 7a63135.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use Card and KpiStrip design system components, add database icons to
section headers, right-align numeric columns, replace text toggles with
chevron icons, and constrain max width to prevent ultra-wide stretching.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The server dashboard link in the sidebar footer is premature — tenant
servers may not be provisioned yet and the link target depends on org
context that isn't always available.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Same hardcoded dev credentials bug as InfrastructureService —
TenantDataCleanupService.dropPostgresSchema() used "cameleer"/"cameleer_dev"
instead of the provisioning properties, causing schema DROP to fail on
production installs during tenant deletion.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
pgConnection() had hardcoded dev credentials ("cameleer"/"cameleer_dev")
instead of using the provisioning properties, causing "password
authentication failed" on production installs where the password is
generated.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three issues fixed:
1. Docker socket: use /var/run/docker.sock instead of Windows named pipe
(//./pipe/docker_engine) — Linux containers can't use named pipes.
2. FQDN detection: reverse-DNS lookup on host IPs to find the FQDN
instead of relying on GetHostEntry which returns bare hostname on
Windows machines with DNS-registered domain suffixes.
3. Reinstall path duplication: Push-Location/Pop-Location in the
reinstall handler used try/catch without finally, so Pop-Location
was skipped when docker compose wrote to stderr under
ErrorActionPreference=Stop. CWD stayed in the install dir, causing
the relative ./cameleer default to resolve to cameleer/cameleer.
4. Logto bootstrap: register admin-console redirect URIs and add the
admin user to Logto's internal organizations (t-default, t-admin)
with the admin role — both required for console login to work.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use /dev/urandom instead of openssl rand for generating random
passwords. Available on all Linux/macOS systems without requiring
openssl to be installed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The verify_health functions passed short service names (postgres,
clickhouse, server, logto) but the actual compose services are
prefixed with cameleer-. This caused docker compose ps -q to return
empty, so health was never read and checks always timed out.
Also renamed server/server-ui service definitions to
cameleer-server/cameleer-server-ui for consistency.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>