--- paths: - "cameleer-server-core/**" --- # Core Module Key Classes `cameleer-server-core/src/main/java/com/cameleer/server/core/` ## agent/ — Agent lifecycle and commands - `AgentRegistryService` — in-memory registry (ConcurrentHashMap), register/heartbeat/lifecycle - `AgentInfo` — record: id, name, application, environmentId, version, routeIds, capabilities, state - `AgentCommand` — record: id, type, targetAgent, payload, createdAt, expiresAt - `AgentEventService` — records agent state changes, heartbeats - `AgentState` — enum: LIVE, STALE, DEAD, SHUTDOWN - `CommandType` — enum for command types (config-update, deep-trace, replay, route-control, etc.) - `CommandStatus` — enum for command acknowledgement states - `CommandReply` — record: command execution result from agent - `AgentEventRecord`, `AgentEventRepository` — event persistence. `AgentEventRepository.queryPage(...)` is cursor-paginated (`AgentEventPage{data, nextCursor, hasMore}`); the legacy non-paginated `query(...)` path is gone. `AgentEventRepository.findInWindow(env, appSlug, agentId, eventTypes, from, to, limit)` returns matching events ordered by `(timestamp ASC, insert_id ASC)` — consumed by `AgentLifecycleEvaluator`. - `AgentEventPage` — record: `(List data, String nextCursor, boolean hasMore)` returned by `AgentEventRepository.queryPage` - `AgentEventListener` — callback interface for agent events - `RouteStateRegistry` — tracks per-agent route states ## runtime/ — App/Environment/Deployment domain - `App` — record: id, environmentId, slug, displayName, containerConfig (JSONB) - `AppVersion` — record: id, appId, version, jarPath, detectedRuntimeType, detectedMainClass - `Environment` — record: id, slug, displayName, production, enabled, defaultContainerConfig, jarRetentionCount, color, createdAt. `color` is one of the 8 preset palette values validated by `EnvironmentColor.VALUES` and CHECK-constrained in PostgreSQL (V2 migration). - `EnvironmentColor` — constants: `DEFAULT = "slate"`, `VALUES = {slate,red,amber,green,teal,blue,purple,pink}`, `isValid(String)`. - `Deployment` — record: id, appId, appVersionId, environmentId, status, targetState, deploymentStrategy, replicaStates (JSONB), deployStage, containerId, containerName, createdBy (String, user_id reference; nullable for pre-V4 historical rows) - `DeploymentStatus` — enum: STOPPED, STARTING, RUNNING, DEGRADED, STOPPING, FAILED. `DEGRADED` is reserved for post-deploy drift (a replica died after RUNNING); `DeploymentExecutor` now marks partial-healthy deploys FAILED, not DEGRADED. - `DeployStage` — enum: PRE_FLIGHT, PULL_IMAGE, CREATE_NETWORK, START_REPLICAS, HEALTH_CHECK, SWAP_TRAFFIC, COMPLETE - `DeploymentStrategy` — enum: BLUE_GREEN, ROLLING. Stored on `ResolvedContainerConfig.deploymentStrategy` as kebab-case string (`"blue-green"` / `"rolling"`). `fromWire(String)` is the only conversion entry point; unknown/null inputs fall back to BLUE_GREEN so the executor dispatch site never null-checks or throws. - `DeploymentService` — createDeployment (calls `deleteFailedByAppAndEnvironment` first so FAILED rows don't pile up; STOPPED rows are preserved as restorable checkpoints), markRunning, markFailed, markStopped - `RuntimeType` — enum: AUTO, SPRING_BOOT, QUARKUS, PLAIN_JAVA, NATIVE - `RuntimeDetector` — probes JAR files at upload time: detects runtime from manifest Main-Class (Spring Boot loader, Quarkus entry point, plain Java) or native binary (non-ZIP magic bytes) - `ContainerRequest` — record: 20 fields for Docker container creation (includes runtimeType, customArgs, mainClass) - `ContainerStatus` — record: state, running, exitCode, error - `ResolvedContainerConfig` — record: typed config with memoryLimitMb, memoryReserveMb, cpuRequest, cpuLimit, appPort, exposedPorts, customEnvVars, stripPathPrefix, sslOffloading, routingMode, routingDomain, serverUrl, replicas, deploymentStrategy, routeControlEnabled, replayEnabled, runtimeType, customArgs, extraNetworks - `RoutingMode` — enum for routing strategies - `ConfigMerger` — pure function: resolve(globalDefaults, envConfig, appConfig) -> ResolvedContainerConfig - `RuntimeOrchestrator` — interface: startContainer, stopContainer, getContainerStatus, getLogs, startLogCapture, stopLogCapture - `AppRepository`, `AppVersionRepository`, `EnvironmentRepository`, `DeploymentRepository` — repository interfaces - `AppService`, `EnvironmentService` — domain services ## search/ — Execution search and stats - `SearchService` — search, count, stats, statsForApp, statsForRoute, timeseries, timeseriesForApp, timeseriesForRoute, timeseriesGroupedByApp, timeseriesGroupedByRoute, slaCompliance, slaCountsByApp, slaCountsByRoute, topErrors, activeErrorTypes, punchcard, distinctAttributeKeys. `statsForRoute`/`timeseriesForRoute` take `(routeId, applicationId)` — app filter is applied to `stats_1m_route`. - `SearchRequest` / `SearchResult` — search DTOs - `ExecutionStats`, `ExecutionSummary` — stats aggregation records - `StatsTimeseries`, `TopError` — timeseries and error DTOs - `LogSearchRequest` / `LogSearchResponse` — log search DTOs. `LogSearchRequest.sources` / `levels` are `List` (null-normalized, multi-value OR); `cursor` + `limit` + `sort` drive keyset pagination. Response carries `nextCursor` + `hasMore` + per-level `levelCounts`. ## storage/ — Storage abstractions - `ExecutionStore`, `MetricsStore`, `MetricsQueryStore`, `StatsStore`, `DiagramStore`, `RouteCatalogStore`, `SearchIndex`, `LogIndex` — interfaces - `RouteCatalogEntry` — record: applicationId, routeId, environment, firstSeen, lastSeen - `LogEntryResult` — log query result record - `model/` — `ExecutionDocument`, `MetricTimeSeries`, `MetricsSnapshot` ## rbac/ — Role-based access control - `RbacService` — interface: role/group CRUD, assignRoleToUser, removeRoleFromUser, addUserToGroup, removeUserFromGroup, getDirectRolesForUser, getEffectiveRolesForUser, clearManagedAssignments, assignManagedRole, addUserToManagedGroup, getStats, listUsers - `SystemRole` — enum: AGENT, VIEWER, OPERATOR, ADMIN; `normalizeScope()` maps scopes - `UserDetail`, `RoleDetail`, `GroupDetail` — records - `UserSummary`, `RoleSummary`, `GroupSummary` — lightweight list records - `RbacStats` — aggregate stats record - `AssignmentOrigin` — enum: DIRECT, CLAIM_MAPPING (tracks how roles were assigned) - `ClaimMappingRule` — record: OIDC claim-to-role mapping rule - `ClaimMappingService` — interface: CRUD for claim mapping rules - `ClaimMappingRepository` — persistence interface - `RoleRepository`, `GroupRepository` — persistence interfaces ## admin/ — Server-wide admin config - `SensitiveKeysConfig` — record: keys (List, immutable) - `SensitiveKeysRepository` — interface: find(), save() - `SensitiveKeysMerger` — pure function: merge(global, perApp) -> union with case-insensitive dedup, preserves first-seen casing. Returns null when both inputs null. - `AppSettings`, `AppSettingsRepository` — per-app-per-env settings config and persistence. Record carries `(applicationId, environment, …)`; repository methods are `findByApplicationAndEnvironment`, `findByEnvironment`, `save`, `delete(appId, env)`. `AppSettings.defaults(appId, env)` produces a default instance scoped to an environment. - `ThresholdConfig`, `ThresholdRepository` — alerting threshold config and persistence - `AuditService` — audit logging facade - `AuditRecord`, `AuditResult`, `AuditCategory` (enum: `INFRA, AUTH, USER_MGMT, CONFIG, RBAC, AGENT, OUTBOUND_CONNECTION_CHANGE, OUTBOUND_HTTP_TRUST_CHANGE, ALERT_RULE_CHANGE, ALERT_SILENCE_CHANGE, DEPLOYMENT`), `AuditRepository` — audit trail records and persistence ## http/ — Outbound HTTP primitives (cross-cutting) - `OutboundHttpClientFactory` — interface: `clientFor(context)` returns memoized `CloseableHttpClient` - `OutboundHttpProperties` — record: `trustAll, trustedCaPemPaths, defaultConnectTimeout, defaultReadTimeout, proxyUrl, proxyUsername, proxyPassword` - `OutboundHttpRequestContext` — record of per-call TLS/timeout overrides; `systemDefault()` static factory - `TrustMode` — enum: `SYSTEM_DEFAULT | TRUST_ALL | TRUST_PATHS` ## outbound/ — Admin-managed outbound connections - `OutboundConnection` — record: id, tenantId, name, description, url, method, defaultHeaders, defaultBodyTmpl, tlsTrustMode, tlsCaPemPaths, hmacSecretCiphertext, auth, allowedEnvironmentIds, createdAt, createdBy (String user_id), updatedAt, updatedBy (String user_id). `isAllowedInEnvironment(envId)` returns true when allowed-envs list is empty OR contains the env. - `OutboundAuth` — sealed interface + records: `None | Bearer(tokenCiphertext) | Basic(username, passwordCiphertext)`. Jackson `@JsonTypeInfo(use = DEDUCTION)` — wire shape has no discriminator, subtype inferred from fields. - `OutboundAuthKind`, `OutboundMethod` — enums - `OutboundConnectionRepository` — CRUD by (tenantId, id): save/findById/findByName/listByTenant/delete - `OutboundConnectionService` — create/update/delete/get/list with uniqueness + narrow-envs + delete-if-referenced guards. `rulesReferencing(id)` stubbed in Plan 01 (returns `[]`); populated in Plan 02 against `AlertRuleRepository`. ## security/ — Auth - `JwtService` — interface: createAccessToken, createRefreshToken, validateAccessToken, validateRefreshToken - `Ed25519SigningService` — interface: sign, getPublicKeyBase64 (config signing) - `OidcConfig` — record: enabled, issuerUri, clientId, clientSecret, rolesClaim, defaultRoles, autoSignup, displayNameClaim, userIdClaim, audience, additionalScopes - `OidcConfigRepository` — persistence interface - `PasswordPolicyValidator` — min 12 chars, 3-of-4 character classes, no username match - `UserInfo`, `UserRepository` — user identity records and persistence - `InvalidTokenException` — thrown on revoked/expired tokens ## ingestion/ — Buffered data pipeline - `IngestionService` — diagram + metrics facade (`ingestDiagram`, `acceptMetrics`, `getMetricsBuffer`). Execution ingestion went through here via the legacy `RouteExecution` shape until `ChunkAccumulator` took over writes from the chunked pipeline — the `ingestExecution` path plus its `ExecutionStore.upsert` / `upsertProcessors` dependencies were removed. - `ChunkAccumulator` — batches data for efficient flush; owns the execution write path (chunks → buffers → flush scheduler → `ClickHouseExecutionStore.insertExecutionBatch`). - `WriteBuffer` — bounded ring buffer for async flush - `BufferedLogEntry` — log entry wrapper with metadata - `MergedExecution`, `TaggedDiagram` — tagged ingestion records. `TaggedDiagram` carries `(instanceId, applicationId, environment, graph)` — env is resolved from the agent registry in the controller and stamped on the ClickHouse `route_diagrams` row.