13 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project
Cameleer Server — observability server that receives, stores, and serves Camel route execution data and route diagrams from Cameleer agents. Pushes config and commands to agents via SSE. Also orchestrates Docker container deployments when running under cameleer-saas.
Related Project
- cameleer (
https://gitea.siegeln.net/cameleer/cameleer) — the Java agent that instruments Camel applications - Protocol defined in
cameleer-common/PROTOCOL.mdin the agent repo - This server depends on
com.cameleer:cameleer-common(shared models and graph API)
Modules
cameleer-server-core— domain logic, storage interfaces, services (no Spring dependencies)cameleer-server-app— Spring Boot web app, REST controllers, SSE, persistence, Docker orchestration
Build Commands
mvn clean compile # Compile all modules
mvn clean verify # Full build with tests
Run
java -jar cameleer-server-app/target/cameleer-server-app-1.0-SNAPSHOT.jar
Key Conventions
- Java 17+ required
- Spring Boot 3.4.3 parent POM
- Depends on
com.cameleer:cameleer-commonfrom Gitea Maven registry - Jackson
JavaTimeModuleforInstantdeserialization - Communication: receives HTTP POST data from agents (executions, diagrams, metrics, logs), serves SSE event streams for config push/commands (config-update, deep-trace, replay, route-control)
- Environment filtering: all data queries filter by the selected environment. All commands target only agents in the selected environment. Backend endpoints accept optional
environmentquery parameter; null = all environments (backward compatible). - Maintains agent instance registry (in-memory) with states: LIVE -> STALE -> DEAD. Auto-heals from JWT
envclaim + heartbeat body on heartbeat/SSE after server restart (priority: heartbeatenvironmentId> JWTenvclaim >"default"). Capabilities and route states updated on every heartbeat (protocol v2). Route catalog merges three sources: in-memory agent registry, persistentroute_catalogtable (ClickHouse), andstats_1m_routeexecution stats. The persistent catalog tracksfirst_seen/last_seenper route per environment, updated on every registration and heartbeat. Routes appear in the sidebar when their lifecycle overlaps the selected time window (first_seen <= to AND last_seen >= from), so historical routes remain visible even after being dropped from newer app versions. - Multi-tenancy: each server instance serves one tenant (configured via
CAMELEER_SERVER_TENANT_ID, default:"default"). Environments (dev/staging/prod) are first-class. PostgreSQL isolated via schema-per-tenant (?currentSchema=tenant_{id}) andApplicationName=tenant_{id}on the JDBC URL. ClickHouse shared DB withtenant_id+environmentcolumns, partitioned by(tenant_id, toYYYYMM(timestamp)). - Storage: PostgreSQL for RBAC, config, and audit; ClickHouse for all observability data (executions, search, logs, metrics, stats, diagrams). ClickHouse schema migrations in
clickhouse/*.sql, run idempotently on startup byClickHouseSchemaInitializer. UseIF NOT EXISTSfor CREATE and ADD PROJECTION. - Log exchange correlation:
ClickHouseLogStoreextractsexchange_idfrom log entry MDC, preferringcameleer.exchangeIdovercamel.exchangeId(fallback for older agents). ForON_COMPLETIONexchange copies, the agent setscameleer.exchangeIdto the parent's exchange ID viaCORRELATION_ID. - Log processor correlation: The agent sets
cameleer.processorIdin MDC, identifying which processor node emitted a log line. - Logging: ClickHouse JDBC set to INFO (
com.clickhouse), HTTP client to WARN (org.apache.hc.client5) in application.yml - Security: JWT auth with RBAC (AGENT/VIEWER/OPERATOR/ADMIN roles), Ed25519 config signing (key derived deterministically from JWT secret via HMAC-SHA256), bootstrap token for registration. CORS:
CAMELEER_SERVER_SECURITY_CORSALLOWEDORIGINS(comma-separated) overridesCAMELEER_SERVER_SECURITY_UIORIGINfor multi-origin setups. Infrastructure access:CAMELEER_SERVER_SECURITY_INFRASTRUCTUREENDPOINTS=falsedisables Database and ClickHouse admin endpoints. Last-ADMIN guard: system prevents removal of the last ADMIN role (409 Conflict). Password policy: min 12 chars, 3-of-4 character classes, no username match. Brute-force protection: 5 failed attempts -> 15 min lockout. Token revocation:token_revoked_beforecolumn on users, checked inJwtAuthenticationFilter, set on password change. - OIDC: Optional external identity provider support (token exchange pattern). Configured via admin API/UI, stored in database (
server_configtable). Resource server mode: accepts external access tokens (Logto M2M) via JWKS validation whenCAMELEER_SERVER_SECURITY_OIDCISSUERURIis set. Scope-based role mapping viaSystemRole.normalizeScope(). System roles synced on every OIDC login viaapplyClaimMappings()inOidcAuthController(callsclearManagedAssignments+assignManagedRoleonRbacService) — always overwrites managed role assignments; uses managed assignment origin to avoid touching group-inherited or directly-assigned roles. Supports ES384, ES256, RS256. - OIDC role extraction:
OidcTokenExchangerreads roles from the access_token first (JWT withat+jwttype), then falls back to id_token.OidcConfigincludesaudience(RFC 8707 resource indicator) andadditionalScopes. All provider-specific configuration is external — no provider-specific code in the server. - Sensitive keys: Global enforced baseline for masking sensitive data in agent payloads. Merge rule:
final = global UNION per-app(case-insensitive dedup, per-app can only add, never remove global keys). - User persistence: PostgreSQL
userstable, admin CRUD at/api/v1/admin/users - Usage analytics: ClickHouse
usage_eventstable tracks authenticated UI requests, flushed every 5s
Database Migrations
PostgreSQL (Flyway): cameleer-server-app/src/main/resources/db/migration/
- V1 — RBAC (users, roles, groups, audit_log)
- V2 — Claim mappings (OIDC)
- V3 — Runtime management (apps, environments, deployments, app_versions)
- V4 — Environment config (default_container_config JSONB)
- V5 — App container config (container_config JSONB on apps)
- V6 — JAR retention policy (jar_retention_count on environments)
- V7 — Deployment orchestration (target_state, deployment_strategy, replica_states JSONB, deploy_stage)
- V8 — Deployment active config (resolved_config JSONB on deployments)
- V9 — Password hardening (failed_login_attempts, locked_until, token_revoked_before on users)
- V10 — Runtime type detection (detected_runtime_type, detected_main_class on app_versions)
ClickHouse: cameleer-server-app/src/main/resources/clickhouse/init.sql (run idempotently on startup)
Maintaining .claude/rules/
When adding, removing, or renaming classes, controllers, endpoints, UI components, or metrics, update the corresponding .claude/rules/ file as part of the same change. The rule files are the class/API map that future sessions rely on — stale rules cause wrong assumptions. Treat rule file updates like updating an import: part of the change, not a separate task.
Disabled Skills
- Do NOT use any
gsd:*skills in this project. This includes all/gsd:prefixed commands.
GitNexus — Code Intelligence
This project is indexed by GitNexus as cameleer-server (6281 symbols, 15871 relationships, 300 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
If any GitNexus tool warns the index is stale, run
npx gitnexus analyzein terminal first.
Always Do
- MUST run impact analysis before editing any symbol. Before modifying a function, class, or method, run
gitnexus_impact({target: "symbolName", direction: "upstream"})and report the blast radius (direct callers, affected processes, risk level) to the user. - MUST run
gitnexus_detect_changes()before committing to verify your changes only affect expected symbols and execution flows. - MUST warn the user if impact analysis returns HIGH or CRITICAL risk before proceeding with edits.
- When exploring unfamiliar code, use
gitnexus_query({query: "concept"})to find execution flows instead of grepping. It returns process-grouped results ranked by relevance. - When you need full context on a specific symbol — callers, callees, which execution flows it participates in — use
gitnexus_context({name: "symbolName"}).
When Debugging
gitnexus_query({query: "<error or symptom>"})— find execution flows related to the issuegitnexus_context({name: "<suspect function>"})— see all callers, callees, and process participationREAD gitnexus://repo/cameleer-server/process/{processName}— trace the full execution flow step by step- For regressions:
gitnexus_detect_changes({scope: "compare", base_ref: "main"})— see what your branch changed
When Refactoring
- Renaming: MUST use
gitnexus_rename({symbol_name: "old", new_name: "new", dry_run: true})first. Review the preview — graph edits are safe, text_search edits need manual review. Then run withdry_run: false. - Extracting/Splitting: MUST run
gitnexus_context({name: "target"})to see all incoming/outgoing refs, thengitnexus_impact({target: "target", direction: "upstream"})to find all external callers before moving code. - After any refactor: run
gitnexus_detect_changes({scope: "all"})to verify only expected files changed.
Never Do
- NEVER edit a function, class, or method without first running
gitnexus_impacton it. - NEVER ignore HIGH or CRITICAL risk warnings from impact analysis.
- NEVER rename symbols with find-and-replace — use
gitnexus_renamewhich understands the call graph. - NEVER commit changes without running
gitnexus_detect_changes()to check affected scope.
Tools Quick Reference
| Tool | When to use | Command |
|---|---|---|
query |
Find code by concept | gitnexus_query({query: "auth validation"}) |
context |
360-degree view of one symbol | gitnexus_context({name: "validateUser"}) |
impact |
Blast radius before editing | gitnexus_impact({target: "X", direction: "upstream"}) |
detect_changes |
Pre-commit scope check | gitnexus_detect_changes({scope: "staged"}) |
rename |
Safe multi-file rename | gitnexus_rename({symbol_name: "old", new_name: "new", dry_run: true}) |
cypher |
Custom graph queries | gitnexus_cypher({query: "MATCH ..."}) |
Impact Risk Levels
| Depth | Meaning | Action |
|---|---|---|
| d=1 | WILL BREAK — direct callers/importers | MUST update these |
| d=2 | LIKELY AFFECTED — indirect deps | Should test |
| d=3 | MAY NEED TESTING — transitive | Test if critical path |
Resources
| Resource | Use for |
|---|---|
gitnexus://repo/cameleer-server/context |
Codebase overview, check index freshness |
gitnexus://repo/cameleer-server/clusters |
All functional areas |
gitnexus://repo/cameleer-server/processes |
All execution flows |
gitnexus://repo/cameleer-server/process/{name} |
Step-by-step execution trace |
Self-Check Before Finishing
Before completing any code modification task, verify:
gitnexus_impactwas run for all modified symbols- No HIGH/CRITICAL risk warnings were ignored
gitnexus_detect_changes()confirms changes match expected scope- All d=1 (WILL BREAK) dependents were updated
Keeping the Index Fresh
After committing code changes, the GitNexus index becomes stale. Re-run analyze to update it:
npx gitnexus analyze
If the index previously included embeddings, preserve them by adding --embeddings:
npx gitnexus analyze --embeddings
To check whether embeddings exist, inspect .gitnexus/meta.json — the stats.embeddings field shows the count (0 means no embeddings). Running analyze without --embeddings will delete any previously generated embeddings.
Claude Code users: A PostToolUse hook handles this automatically after
git commitandgit merge.
CLI
| Task | Read this skill file |
|---|---|
| Understand architecture / "How does X work?" | .claude/skills/gitnexus/gitnexus-exploring/SKILL.md |
| Blast radius / "What breaks if I change X?" | .claude/skills/gitnexus/gitnexus-impact-analysis/SKILL.md |
| Trace bugs / "Why is X failing?" | .claude/skills/gitnexus/gitnexus-debugging/SKILL.md |
| Rename / extract / split / refactor | .claude/skills/gitnexus/gitnexus-refactoring/SKILL.md |
| Tools, resources, schema reference | .claude/skills/gitnexus/gitnexus-guide/SKILL.md |
| Index, status, clean, wiki CLI commands | .claude/skills/gitnexus/gitnexus-cli/SKILL.md |