Enable deploying feature branches into isolated environments on the same
k3s cluster. Each branch gets its own namespace (cam-<slug>), PostgreSQL
schema, and OpenSearch index prefix for data isolation while sharing the
underlying infrastructure.
- Make OpenSearch index prefix and DB schema configurable via env vars
(defaults preserve existing behavior)
- Restructure deploy/ into Kustomize base + overlays (main/feature)
- Extend CI to build Docker images for all branches, not just main
- Add deploy-feature job with namespace creation, secret copying,
Traefik Ingress routing (<slug>-api/ui.cameleer.siegeln.net)
- Add cleanup-branch job to remove namespace, PG schema, OS indices
on branch deletion
- Install required tools (git, jq, curl) in CI deploy containers
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Set failsafe reuseForks=true to reuse JVM across IT classes (faster test suite)
- Replace ClickHouse with PostgreSQL+OpenSearch in docker-compose.yml
- Remove redundant docker-compose.dev.yml
- Update CLAUDE.md and HOWTO.md to reflect new storage stack
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Use singleton container pattern for PostgreSQL + OpenSearch testcontainers
(fixes container lifecycle issues with @TestInstance(PER_CLASS))
- Fix table name route_executions → executions in DetailControllerIT and
ExecutionControllerIT
- Serialize processor headers as JSON (ObjectMapper) instead of Map.toString()
for JSONB column compatibility
- Add nested mapping for processors field in OpenSearch index template
- Use .keyword sub-field for term queries on dynamically mapped text fields
- Add wildcard fallback queries for all text searches (substring matching)
- Isolate stats tests with unique route names to prevent data contamination
- Wait for OpenSearch indexing in SearchControllerIT with targeted Awaitility
- Reduce OpenSearch debounce to 100ms in test profile
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- SearchControllerIT: remove @TestInstance(PER_CLASS), use @BeforeEach with
static guard, fix table name (route_executions -> executions), remove
Awaitility polling
- OpenSearchIndexIT: replace Thread.sleep with explicit index refresh via
OpenSearchClient
- DiagramLinkingIT: fix table name, remove Awaitility awaits (writes are
synchronous)
- IngestionSchemaIT: rewrite queries for PostgreSQL relational model
(processor_executions table instead of ClickHouse array columns)
- PostgresStatsStoreIT: use explicit time bounds in
refresh_continuous_aggregate calls
- IngestionService: populate diagramContentHash during execution ingestion
by looking up the latest diagram for the route+agent
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace ClickHouse credentials secret with postgres-credentials and
opensearch-credentials secrets. Update deploy step to apply postgres.yaml
and opensearch.yaml manifests instead of clickhouse.yaml, with appropriate
rollout status checks for each StatefulSet.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Delete all ClickHouse storage implementations and config
- Delete old core interfaces (ExecutionRepository, DiagramRepository, MetricsRepository, SearchEngine, RawExecutionRow)
- Delete ClickHouse SQL migration files
- Delete AbstractClickHouseIT
- Update controllers to use new store interfaces (DiagramStore, ExecutionStore)
- Fix IngestionService calls in controllers for new synchronous API
- Migrate all ITs from AbstractClickHouseIT to AbstractPostgresIT
- Fix count() syntax and remove ClickHouse-specific test assertions
- Update TreeReconstructionTest for new buildTree() method
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Design to replace ClickHouse with PostgreSQL/TimescaleDB + OpenSearch.
PostgreSQL as source of truth with continuous aggregates for analytics,
OpenSearch for full-text wildcard search. 21-task implementation plan.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace disconnected Transactions/Applications pages with a persistent
collapsible sidebar listing apps by health status. Add app-scoped view
(/apps/:group) with filtered stats, route chips, and scoped table.
Merge Processor Tree into diagram detail panel with Inspector/Tree
toggle and resizable divider. Remove max-width constraint for full
viewport usage. All view states are deep-linkable via URL.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The empty servers list caused Swagger UI to construct request URLs
without the /api/v1 prefix, resulting in CORS/fetch failures.
Adding a relative server entry makes paths resolve correctly.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- New /swagger route with lazy-loaded SwaggerPage that initializes
swagger-ui-dist and injects the session JWT via requestInterceptor
- Move API link from primary nav to navRight utility area (pill style)
- Code-split swagger chunk (~1.4 MB) so main bundle stays lean
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PerformanceTab and RouteHeader computed new Date().toISOString() on every
render, producing unique millisecond timestamps that busted the React Query
cache key — causing continuous refetches (every few ms instead of 10s).
Round timestamps to 10-second boundaries with useMemo so the query key
stays stable between renders.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The active-count query scanned all wide rows on the base table, exceeding
the 3.6 GiB memory limit. Use PREWHERE status = 'RUNNING' so ClickHouse
reads only the status column first. Add SETTINGS max_memory_usage = 1 GiB
to all queries so concurrent requests degrade gracefully instead of crashing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Row click in ExecutionExplorer now navigates directly to RoutePage with
View Transition instead of expanding an inline panel. Route column is a
clickable link for context-free navigation. Search state syncs to URL
params for back-nav preservation, and previously-visited rows flash on
return. RoutePage gains an Exchange tab showing execution metadata/body/
errors. New /apps page lists application groups with status and route
links, accessible from TopNav.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The JDBC driver sends java.sql.Timestamp with nanoseconds as a string
(e.g. '2026-03-15 10:13:58.105931162') which DateTime('UTC') rejects.
Add bucketTimestamp() helper that truncates to seconds for all rollup
query parameters.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
JDBC sends Timestamp params as strings, causing toStartOfFiveMinutes()
to fail with 'Illegal type String'. Floor to 5-minute boundaries in
Java instead and pass plain bucket >= ? comparisons.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>