Previously `TraefikLabelBuilder` hardcoded `tls.certresolver=default` on every router. That assumes a resolver literally named `default` exists in the Traefik static config — true for ACME-backed installs, false for dev/local installs that use a file-based TLS store. Traefik logs "Router uses a nonexistent certificate resolver" for the bogus resolver on every managed app, and any future attempt to define a differently- named real resolver would silently skip these routers. Server-wide setting via `CAMELEER_SERVER_RUNTIME_CERTRESOLVER` (empty by default) flows through `ConfigMerger.GlobalRuntimeDefaults.certResolver` into `ResolvedContainerConfig.certResolver`. When blank the `tls.certresolver` label is omitted entirely; `tls=true` is still emitted so Traefik serves the default TLS-store cert. When set, the label is emitted with the configured resolver name. Not per-app/per-env configurable: there is one Traefik per server instance and one resolver config; app-level override would only let users break their own routers. TDD: TraefikLabelBuilderTest gains 3 cases (resolver set, null, blank). Full unit suite 211/0/0. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
11 KiB
11 KiB
paths
| paths | |
|---|---|
|
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/lifecycleAgentInfo— record: id, name, application, environmentId, version, routeIds, capabilities, stateAgentCommand— record: id, type, targetAgent, payload, createdAt, expiresAtAgentEventService— records agent state changes, heartbeatsAgentState— enum: LIVE, STALE, DEAD, SHUTDOWNCommandType— enum for command types (config-update, deep-trace, replay, route-control, etc.)CommandStatus— enum for command acknowledgement statesCommandReply— record: command execution result from agentAgentEventRecord,AgentEventRepository— event persistence.AgentEventRepository.queryPage(...)is cursor-paginated (AgentEventPage{data, nextCursor, hasMore}); the legacy non-paginatedquery(...)path is gone.AgentEventRepository.findInWindow(env, appSlug, agentId, eventTypes, from, to, limit)returns matching events ordered by(timestamp ASC, insert_id ASC)— consumed byAgentLifecycleEvaluator.AgentEventPage— record:(List<AgentEventRecord> data, String nextCursor, boolean hasMore)returned byAgentEventRepository.queryPageAgentEventListener— callback interface for agent eventsRouteStateRegistry— 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, detectedMainClassEnvironment— record: id, slug, displayName, production, enabled, defaultContainerConfig, jarRetentionCount, color, createdAt.coloris one of the 8 preset palette values validated byEnvironmentColor.VALUESand 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.DEGRADEDis reserved for post-deploy drift (a replica died after RUNNING);DeploymentExecutornow marks partial-healthy deploys FAILED, not DEGRADED.DeployStage— enum: PRE_FLIGHT, PULL_IMAGE, CREATE_NETWORK, START_REPLICAS, HEALTH_CHECK, SWAP_TRAFFIC, COMPLETEDeploymentStrategy— enum: BLUE_GREEN, ROLLING. Stored onResolvedContainerConfig.deploymentStrategyas 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 (callsdeleteFailedByAppAndEnvironmentfirst so FAILED rows don't pile up; STOPPED rows are preserved as restorable checkpoints), markRunning, markFailed, markStoppedRuntimeType— enum: AUTO, SPRING_BOOT, QUARKUS, PLAIN_JAVA, NATIVERuntimeDetector— 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, errorResolvedContainerConfig— record: typed config with memoryLimitMb, memoryReserveMb, cpuRequest, cpuLimit, appPort, exposedPorts, customEnvVars, stripPathPrefix, sslOffloading, routingMode, routingDomain, serverUrl, replicas, deploymentStrategy, routeControlEnabled, replayEnabled, runtimeType, customArgs, extraNetworks, externalRouting (defaulttrue; whenfalse,TraefikLabelBuilderstrips alltraefik.*labels so the container is not publicly routed), certResolver (server-wide, sourced fromCAMELEER_SERVER_RUNTIME_CERTRESOLVER; when blank thetls.certresolverlabel is omitted — use for dev installs with a static TLS store)RoutingMode— enum for routing strategiesConfigMerger— pure function: resolve(globalDefaults, envConfig, appConfig) -> ResolvedContainerConfigRuntimeOrchestrator— interface: startContainer, stopContainer, getContainerStatus, getLogs, startLogCapture, stopLogCaptureAppRepository,AppVersionRepository,EnvironmentRepository,DeploymentRepository— repository interfacesAppService,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/timeseriesForRoutetake(routeId, applicationId)— app filter is applied tostats_1m_route.SearchRequest/SearchResult— search DTOsExecutionStats,ExecutionSummary— stats aggregation recordsStatsTimeseries,TopError— timeseries and error DTOsLogSearchRequest/LogSearchResponse— log search DTOs.LogSearchRequest.sources/levelsareList<String>(null-normalized, multi-value OR);cursor+limit+sortdrive keyset pagination. Response carriesnextCursor+hasMore+ per-levellevelCounts.
storage/ — Storage abstractions
ExecutionStore,MetricsStore,MetricsQueryStore,StatsStore,DiagramStore,RouteCatalogStore,SearchIndex,LogIndex— interfacesRouteCatalogEntry— record: applicationId, routeId, environment, firstSeen, lastSeenLogEntryResult— log query result recordmodel/—ExecutionDocument,MetricTimeSeries,MetricsSnapshot
rbac/ — Role-based access control
RbacService— interface: role/group CRUD, assignRoleToUser, removeRoleFromUser, addUserToGroup, removeUserFromGroup, getDirectRolesForUser, getEffectiveRolesForUser, clearManagedAssignments, assignManagedRole, addUserToManagedGroup, getStats, listUsersSystemRole— enum: AGENT, VIEWER, OPERATOR, ADMIN;normalizeScope()maps scopesUserDetail,RoleDetail,GroupDetail— recordsUserSummary,RoleSummary,GroupSummary— lightweight list recordsRbacStats— aggregate stats recordAssignmentOrigin— enum: DIRECT, CLAIM_MAPPING (tracks how roles were assigned)ClaimMappingRule— record: OIDC claim-to-role mapping ruleClaimMappingService— interface: CRUD for claim mapping rulesClaimMappingRepository— persistence interfaceRoleRepository,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 arefindByApplicationAndEnvironment,findByEnvironment,save,delete(appId, env).AppSettings.defaults(appId, env)produces a default instance scoped to an environment.ThresholdConfig,ThresholdRepository— alerting threshold config and persistenceAuditService— audit logging facadeAuditRecord,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 memoizedCloseableHttpClientOutboundHttpProperties— record:trustAll, trustedCaPemPaths, defaultConnectTimeout, defaultReadTimeout, proxyUrl, proxyUsername, proxyPasswordOutboundHttpRequestContext— record of per-call TLS/timeout overrides;systemDefault()static factoryTrustMode— 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— enumsOutboundConnectionRepository— CRUD by (tenantId, id): save/findById/findByName/listByTenant/deleteOutboundConnectionService— create/update/delete/get/list with uniqueness + narrow-envs + delete-if-referenced guards.rulesReferencing(id)stubbed in Plan 01 (returns[]); populated in Plan 02 againstAlertRuleRepository.
security/ — Auth
JwtService— interface: createAccessToken, createRefreshToken, validateAccessToken, validateRefreshTokenEd25519SigningService— interface: sign, getPublicKeyBase64 (config signing)OidcConfig— record: enabled, issuerUri, clientId, clientSecret, rolesClaim, defaultRoles, autoSignup, displayNameClaim, userIdClaim, audience, additionalScopesOidcConfigRepository— persistence interfacePasswordPolicyValidator— min 12 chars, 3-of-4 character classes, no username matchUserInfo,UserRepository— user identity records and persistenceInvalidTokenException— thrown on revoked/expired tokens
ingestion/ — Buffered data pipeline
IngestionService— diagram + metrics facade (ingestDiagram,acceptMetrics,getMetricsBuffer). Execution ingestion went through here via the legacyRouteExecutionshape untilChunkAccumulatortook over writes from the chunked pipeline — theingestExecutionpath plus itsExecutionStore.upsert/upsertProcessorsdependencies 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 flushBufferedLogEntry— log entry wrapper with metadataMergedExecution,TaggedDiagram— tagged ingestion records.TaggedDiagramcarries(instanceId, applicationId, environment, graph)— env is resolved from the agent registry in the controller and stamped on the ClickHouseroute_diagramsrow.