Multitenancy: tenant isolation + environment support #123
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
Cameleer3 Server is being integrated into a SaaS platform (cameleer-saas). The server must support multiple tenants sharing PostgreSQL and ClickHouse while guaranteeing strict data isolation. Each tenant gets their own cameleer3-server instance. Environments (dev/staging/prod) are a first-class concept within each tenant.
Design spec:
docs/superpowers/specs/2026-04-04-multitenancy-design.mdData Hierarchy
Key Decisions
currentSchema)tenant_idin partition keytenantclaimScope
1. Server Configuration
TenantPropertiesconfig bean readingCAMELEER_TENANT_ID(default:"default")?currentSchema=tenant_{id}2. Agent Protocol (cameleer3-common)
environmentIdto registration payload (default:"default")environmentIdto heartbeat payload (for auto-heal)tenant+envclaims to agent JWT3. Agent Registry
environmentIdtoAgentInforecord4. ClickHouse Schema (fresh install, no migration)
environmentcolumn to all tables (DEFAULT'default')(tenant_id, timestamp, environment, application_id, ...)(tenant_id, toYYYYMM(timestamp))environmenttenant_idcolumn tousage_eventstable5. ClickHouse Stores (8 files)
ClickHouseExecutionStore— replace hardcoded'default'with injected tenant ID, add environmentClickHouseLogStore— sameClickHouseMetricsStore— add tenant_id to INSERT (currently missing)ClickHouseMetricsQueryStore— add tenant_id filter to reads (currently missing)ClickHouseStatsStore— replaceTENANTconstant with injected value, add environment filterClickHouseDiagramStore— replaceTENANTconstantClickHouseSearchIndex— replace hardcoded'default'ClickHouseAgentEventRepository— replaceTENANTconstantClickHouseUsageTracker— add tenant_id to writes and reads6. Write Pipeline
ChunkAccumulator— extractenvironmentIdfrom agent registry, include inMergedExecutionandProcessorBatchMergedExecution— addenvironmentfieldProcessorBatch— addenvironmentfieldBufferedLogEntry— addenvironmentfield7. UI
Current State (Audit)
What exists:
tenant_idcolumns (DEFAULT'default')tenant_idtenantId(always"default")What's missing:
environmentcolumn anywheretenant_id = 'default'usage_eventstable has notenant_idcolumnagent_metricsINSERT doesn't includetenant_idAgentInfohas noenvironmentIdVerification
CAMELEER_TENANT_ID=acme→ PG connects totenant_acmeschemaenvironmentId=dev→ CH writes containtenant_id='acme',environment='dev'CAMELEER_TENANT_ID=beta→ data isolated