# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Cameleer SaaS — multi-tenant SaaS platform wrapping the Cameleer observability stack (Java agent + server) for Apache Camel applications. Customers get managed observability for their Camel integrations without running infrastructure. ## Ecosystem This repo is the SaaS layer on top of two proven components: - **cameleer3** (sibling repo) — Java agent using ByteBuddy for zero-code instrumentation of Camel apps. Captures route executions, processor traces, payloads, metrics, and route graph topology. Deploys as `-javaagent` JAR. - **cameleer3-server** (sibling repo) — Spring Boot observability backend. Receives agent data via HTTP, pushes config/commands via SSE. PostgreSQL + OpenSearch storage. React SPA dashboard. JWT auth with Ed25519 config signing. - **cameleer-website** — Marketing site (Astro 5) - **design-system** — Shared React component library (`@cameleer/design-system` on Gitea npm registry) Agent-server protocol is defined in `cameleer3/cameleer3-common/PROTOCOL.md`. The agent and server are mature, proven components — this repo wraps them with multi-tenancy, billing, and self-service onboarding. ## Architecture Context The existing cameleer3-server already has single-tenant auth (JWT, RBAC, bootstrap tokens, OIDC). The SaaS layer must: - Add multi-tenancy (tenant isolation of agent data, diagrams, configs) - Provide self-service signup, billing, and team management - Generate per-tenant bootstrap tokens for agent registration - Proxy or federate access to tenant-specific cameleer3-server instances - Enforce usage quotas and metered billing ### Routing (single-domain, path-based via Traefik) All services on one hostname. Two env vars control everything: `PUBLIC_HOST` + `PUBLIC_PROTOCOL`. | Path | Target | Notes | |------|--------|-------| | `/platform/*` | cameleer-saas:8080 | SPA + API (`server.servlet.context-path: /platform`) | | `/server/*` | cameleer3-server-ui:80 | Server dashboard (strip-prefix + `BASE_PATH=/server`) | | `/` | redirect → `/platform/` | Via `docker/traefik-dynamic.yml` | | `/*` (catch-all) | logto:3001 (priority=1) | Sign-in, OIDC, interaction, assets | - SPA assets at `/_app/` (Vite `assetsDir: '_app'`) to avoid conflict with Logto's `/assets/` - Logto `ENDPOINT` = `${PUBLIC_PROTOCOL}://${PUBLIC_HOST}` (same domain, same origin) - TLS: self-signed cert init container (`traefik-certs`) for dev, ACME for production - Root `/` → `/platform/` redirect via Traefik file provider (`docker/traefik-dynamic.yml`) ### Auth enforcement - All API endpoints enforce OAuth2 scopes via `@PreAuthorize("hasAuthority('SCOPE_xxx')")` annotations - Tenant isolation enforced by `TenantIsolationInterceptor` (a single `HandlerInterceptor` on `/api/**` that resolves JWT org_id to TenantContext and validates `{tenantId}`, `{environmentId}`, `{appId}` path variables; fail-closed, platform admins bypass) - 10 OAuth2 scopes defined on the Logto API resource (`https://api.cameleer.local`), served to the frontend from `GET /platform/api/config` - Custom `JwtDecoder` in `SecurityConfig.java` — ES384 algorithm, `at+jwt` token type, split issuer-uri (string validation) / jwk-set-uri (Docker-internal fetch) ### Server integration (cameleer3-server env vars) | Env var | Value | Purpose | |---------|-------|---------| | `CAMELEER_OIDC_ISSUER_URI` | `${PUBLIC_PROTOCOL}://${PUBLIC_HOST}/oidc` | Token issuer claim validation | | `CAMELEER_OIDC_JWK_SET_URI` | `http://logto:3001/oidc/jwks` | Docker-internal JWK fetch | | `CAMELEER_OIDC_TLS_SKIP_VERIFY` | `true` | Skip cert verify for OIDC discovery (dev) | | `CAMELEER_CORS_ALLOWED_ORIGINS` | `${PUBLIC_PROTOCOL}://${PUBLIC_HOST}` | Allow browser requests through Traefik | | `BASE_PATH` (server-ui) | `/server` | React Router basename + `` tag | ## Related Conventions - Gitea-hosted: `gitea.siegeln.net/cameleer/` - CI: `.gitea/workflows/` — Gitea Actions - K8s target: k3s cluster at 192.168.50.86 - Docker builds: multi-stage, buildx with registry cache, `--provenance=false` for Gitea compatibility - Design system: import from `@cameleer/design-system` (Gitea npm registry) ## Disabled Skills - Do NOT use any `gsd:*` skills in this project. This includes all `/gsd:` prefixed commands.