Files
cameleer-server/.claude/rules/app-classes.md
hsiegeln 9b1ef51d77
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 1m27s
CI / docker (push) Successful in 1m10s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 1m40s
SonarQube / sonarqube (push) Successful in 4m29s
feat!: scope per-app config and settings by environment
BREAKING: wipe dev PostgreSQL before deploying — V1 checksum changes.
Agents must now send environmentId on registration (400 if missing).

Two tables previously keyed on app name alone caused cross-environment
data bleed: writing config for (app=X, env=dev) would overwrite the row
used by (app=X, env=prod) agents, and agent startup fetches ignored env
entirely.

- V1 schema: application_config and app_settings are now PK (app, env).
- Repositories: env-keyed finders/saves; env is the authoritative column,
  stamped on the stored JSON so the row agrees with itself.
- ApplicationConfigController.getConfig is dual-mode — AGENT role uses
  JWT env claim (agents cannot spoof env); non-agent callers provide env
  via ?environment= query param.
- AppSettingsController endpoints now require ?environment=.
- SensitiveKeysAdminController fan-out iterates (app, env) slices so each
  env gets its own merged keys.
- DiagramController ingestion stamps env on TaggedDiagram; ClickHouse
  route_diagrams INSERT + findProcessorRouteMapping are env-scoped.
- AgentRegistrationController: environmentId is required on register;
  removed all "default" fallbacks from register/refresh/heartbeat auto-heal.
- UI hooks (useApplicationConfig, useProcessorRouteMapping, useAppSettings,
  useAllAppSettings, useUpdateAppSettings) take env, wired to
  useEnvironmentStore at all call sites.
- New ConfigEnvIsolationIT covers env-isolation for both repositories.

Plan in docs/superpowers/plans/2026-04-16-environment-scoping.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 22:25:21 +02:00

9.2 KiB

paths
paths
cameleer-server-app/**

App Module Key Classes

cameleer-server-app/src/main/java/com/cameleer/server/app/

controller/ — REST endpoints

  • AgentRegistrationController — POST /register (requires environmentId in body; 400 if missing/blank), POST /heartbeat (env from body environmentId → JWT env claim; 400 if neither present during auto-heal), GET / (list), POST /refresh-token (rejects tokens with no env claim)
  • AgentSseController — GET /sse (Server-Sent Events connection)
  • AgentCommandController — POST /broadcast, POST /{agentId}, POST /{agentId}/ack
  • AppController — CRUD /api/v1/apps, POST /{appId}/upload-jar, GET /{appId}/versions
  • DeploymentController — GET/POST /api/v1/apps/{appId}/deployments, POST /{id}/stop, POST /{id}/promote, GET /{id}/logs
  • EnvironmentAdminController — CRUD /api/v1/admin/environments, PUT /{id}/jar-retention
  • ExecutionController — GET /api/v1/executions (search + detail)
  • SearchController — POST /api/v1/search, GET /routes, GET /top-errors, GET /punchcard
  • LogQueryController — GET /api/v1/logs (filters: source, application, agentId, exchangeId, level, logger, q, environment, time range)
  • LogIngestionController — POST /api/v1/data/logs (accepts List<LogEntry> JSON array, each entry has source: app/agent). Logs WARN for: missing agent identity, unregistered agents, empty payloads, buffer-full drops, deserialization failures. Normal acceptance at DEBUG.
  • CatalogController — GET /api/v1/catalog (unified app catalog merging PG managed apps + in-memory agents + CH stats), DELETE /api/v1/catalog/{applicationId} (ADMIN: dismiss app, purge all CH data + PG record). Auto-filters discovered apps older than discoveryttldays with no live agents.
  • ChunkIngestionController — POST /api/v1/ingestion/chunk/{executions|metrics|diagrams}
  • UserAdminController — CRUD /api/v1/admin/users, POST /{id}/roles, POST /{id}/set-password
  • RoleAdminController — CRUD /api/v1/admin/roles
  • GroupAdminController — CRUD /api/v1/admin/groups
  • OidcConfigAdminController — GET/POST /api/v1/admin/oidc, POST /test
  • SensitiveKeysAdminController — GET/PUT /api/v1/admin/sensitive-keys. GET returns 200 with config or 204 if not configured. PUT accepts { keys: [...] } with optional ?pushToAgents=true. The fan-out iterates over every distinct (application, environment) slice (from persisted application_config rows plus currently-registered agents) and pushes per-slice merged keys — intentional global baseline + per-env overrides. Stored in server_config table (key sensitive_keys).
  • AuditLogController — GET /api/v1/admin/audit
  • MetricsController — GET /api/v1/metrics, GET /timeseries
  • DiagramController — GET /api/v1/diagrams/{id}, POST /api/v1/data/diagrams. Ingestion resolves applicationId + environment from the agent registry (keyed on JWT subject) and stamps both on the stored TaggedDiagram. route_diagrams CH table has an environment column; queries like findProcessorRouteMapping(app, env) filter by it.
  • DiagramRenderController — POST /api/v1/diagrams/render (ELK layout)
  • ClaimMappingAdminController — CRUD /api/v1/admin/claim-mappings, POST /test (accepts inline rules + claims for preview without saving)
  • LicenseAdminController — GET/POST /api/v1/admin/license
  • AgentEventsController — GET /api/v1/agent-events (agent state change history)
  • AgentMetricsController — GET /api/v1/agent-metrics (JVM/Camel metrics per agent instance)
  • AppSettingsController — GET/PUT /api/v1/admin/app-settings (list), /api/v1/admin/app-settings/{appId} (per-app). All endpoints require ?environment=.
  • ApplicationConfigController/api/v1/config (agent/admin observability config: traced processors, taps, route recording, per-app sensitive keys). GET list requires ?environment=. GET/PUT/DELETE for a single app are env-scoped: for AGENT role the env comes from the JWT env claim (query param ignored, agents cannot spoof env); for non-agent callers env must be supplied via ?environment= (user JWTs carry a placeholder env="default" that is NOT authoritative). defaultConfig(application, environment) is returned when no row exists.
  • ClickHouseAdminController — GET /api/v1/admin/clickhouse (ClickHouse admin, conditional on infrastructure endpoints)
  • DatabaseAdminController — GET /api/v1/admin/database (PG admin, conditional on infrastructure endpoints)
  • DetailController — GET /api/v1/detail (execution detail with processor tree)
  • EventIngestionController — POST /api/v1/data/events (agent event ingestion)
  • RbacStatsController — GET /api/v1/admin/rbac/stats
  • RouteCatalogController — GET /api/v1/routes/catalog (merged route catalog from registry + ClickHouse)
  • RouteMetricsController — GET /api/v1/route-metrics (per-route Camel metrics)
  • ThresholdAdminController — CRUD /api/v1/admin/thresholds
  • UsageAnalyticsController — GET /api/v1/admin/usage (ClickHouse usage_events)

runtime/ — Docker orchestration

  • DockerRuntimeOrchestrator — implements RuntimeOrchestrator; Docker Java client (zerodep transport), container lifecycle
  • DeploymentExecutor — @Async staged deploy: PRE_FLIGHT -> PULL_IMAGE -> CREATE_NETWORK -> START_REPLICAS -> HEALTH_CHECK -> SWAP_TRAFFIC -> COMPLETE. Container names are {tenantId}-{envSlug}-{appSlug}-{replicaIndex} (globally unique on Docker daemon). Sets per-replica CAMELEER_AGENT_INSTANCEID env var to {envSlug}-{appSlug}-{replicaIndex}.
  • DockerNetworkManager — ensures bridge networks (cameleer-traefik, cameleer-env-{slug}), connects containers
  • DockerEventMonitor — persistent Docker event stream listener (die, oom, start, stop), updates deployment status
  • TraefikLabelBuilder — generates Traefik Docker labels for path-based or subdomain routing. Also emits cameleer.replica and cameleer.instance-id labels per container for labels-first identity.
  • PrometheusLabelBuilder — generates Prometheus Docker labels (prometheus.scrape/path/port) per runtime type for docker_sd_configs auto-discovery
  • ContainerLogForwarder — streams Docker container stdout/stderr to ClickHouse with source='container'. One follow-stream thread per container, batches lines every 2s/50 lines via ClickHouseLogStore.insertBufferedBatch(). 60-second max capture timeout.
  • DisabledRuntimeOrchestrator — no-op when runtime not enabled

metrics/ — Prometheus observability

  • ServerMetrics — centralized business metrics: gauges (agents by state, SSE connections, buffer depths), counters (ingestion drops, agent transitions, deployment outcomes, auth failures), timers (flush duration, deployment duration). Exposed via /api/v1/prometheus.

storage/ — PostgreSQL repositories (JdbcTemplate)

  • PostgresAppRepository, PostgresAppVersionRepository, PostgresEnvironmentRepository
  • PostgresDeploymentRepository — includes JSONB replica_states, deploy_stage, findByContainerId
  • PostgresUserRepository, PostgresRoleRepository, PostgresGroupRepository
  • PostgresAuditRepository, PostgresOidcConfigRepository, PostgresClaimMappingRepository, PostgresSensitiveKeysRepository
  • PostgresAppSettingsRepository, PostgresApplicationConfigRepository, PostgresThresholdRepository. Both app_settings and application_config are env-scoped (PK (app_id, environment) / (application, environment)); finders take (app, env) — no env-agnostic variants.

storage/ — ClickHouse stores

  • ClickHouseExecutionStore, ClickHouseMetricsStore, ClickHouseMetricsQueryStore
  • ClickHouseStatsStore — pre-aggregated stats, punchcard
  • ClickHouseDiagramStore, ClickHouseAgentEventRepository
  • ClickHouseUsageTracker — usage_events for billing
  • ClickHouseRouteCatalogStore — persistent route catalog with first_seen cache, warm-loaded on startup

search/ — ClickHouse search and log stores

  • ClickHouseLogStore — log storage and query, MDC-based exchange/processor correlation
  • ClickHouseSearchIndex — full-text search

security/ — Spring Security

  • SecurityConfig — WebSecurityFilterChain, JWT filter, CORS, OIDC conditional
  • JwtAuthenticationFilter — OncePerRequestFilter, validates Bearer tokens
  • JwtServiceImpl — HMAC-SHA256 JWT (Nimbus JOSE)
  • OidcAuthController — /api/v1/auth/oidc (login-uri, token-exchange, logout)
  • OidcTokenExchanger — code -> tokens, role extraction from access_token then id_token
  • OidcProviderHelper — OIDC discovery, JWK source cache

agent/ — Agent lifecycle

  • SseConnectionManager — manages per-agent SSE connections, delivers commands
  • AgentLifecycleMonitor — @Scheduled 10s, LIVE->STALE->DEAD transitions
  • SsePayloadSigner — Ed25519 signs SSE payloads for agent verification

retention/ — JAR cleanup

  • JarRetentionJob — @Scheduled 03:00 daily, per-environment retention, skips deployed versions

config/ — Spring beans

  • RuntimeOrchestratorAutoConfig — conditional Docker/Disabled orchestrator + NetworkManager + EventMonitor
  • RuntimeBeanConfig — DeploymentExecutor, AppService, EnvironmentService
  • SecurityBeanConfig — JwtService, Ed25519, BootstrapTokenValidator
  • StorageBeanConfig — all repositories
  • ClickHouseConfig — ClickHouse JdbcTemplate, schema initializer