Commit Graph

1621 Commits

Author SHA1 Message Date
hsiegeln
5c9323cfed feat(search): accept attr= multi-value query param on /executions GET
Add a repeatable attr query parameter to the GET /executions endpoint that
parses key-only (exists check) and key:value (exact or wildcard-via-*)
filters. Invalid keys are mapped to HTTP 400 via ResponseStatusException.
The POST /executions/search path already honoured attributeFilters from
the request body via the Jackson canonical ctor; an IT now proves it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 10:23:52 +02:00
hsiegeln
2dcbd5a772 feat(search): push AttributeFilter list into ClickHouse WHERE clause
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 10:13:30 +02:00
hsiegeln
f9b5f235cc feat(search): extend SearchRequest with attributeFilters (legacy ctor preserved) 2026-04-24 09:59:05 +02:00
hsiegeln
0b419db9f1 feat(search): add AttributeFilter record with key regex + wildcard pattern translation 2026-04-24 09:51:28 +02:00
hsiegeln
5f6f9e523d chore(gitnexus): sync indexed symbol count
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 09:20:25 +02:00
hsiegeln
35319dc666 refactor(ui): server metrics page uses global time range
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 1m31s
CI / docker (push) Successful in 1m10s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 44s
Drop the page-local DS Select window picker. Drive from() / to() off
useGlobalFilters().timeRange so the dashboard tracks the same TopBar range
as Exchanges / Dashboard / Runtime. Bucket size auto-scales via
stepSecondsFor(windowSeconds) (10 s for ≤30 min → 1 h for >48 h). Query
hooks now take ServerMetricsRange = { from: Date; to: Date } instead of a
windowSeconds number, so they support arbitrary absolute or rolling ranges
the TopBar may supply (not just "now − N"). Toolbar collapses to just the
server-instance badges.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 09:19:20 +02:00
hsiegeln
3c2409ed6e docs(server-metrics): document the built-in admin dashboard
SERVER-CAPABILITIES.md now lists the two consumption paths (UI + REST API)
side-by-side with visibility rules; the dashboard-builder doc leads with a
"Built-in admin dashboard" section and a 2026-04-24 changelog entry so
first-time readers know they don't have to build anything before seeing
server health.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 09:05:22 +02:00
hsiegeln
ca401363ec chore(gitnexus): sync indexed symbol count
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 1m21s
CI / docker (push) Successful in 1m16s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 45s
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 09:01:48 +02:00
hsiegeln
b5ee9e1d1f feat(ui): server metrics admin dashboard
Adds /admin/server-metrics page mirroring the Database/ClickHouse visibility
rules: sidebar entry gated on capabilities.infrastructureEndpoints, backend
controller now has @ConditionalOnProperty(infrastructureendpoints) and
class-level @PreAuthorize('hasRole(ADMIN)'). Dashboard panels are driven
from docs/server-self-metrics.md via the generic
/api/v1/admin/server-metrics/{catalog,instances,query} API — Server Health,
JVM, HTTP & DB pools, and conditionally Alerting + Deployments when their
metrics appear in the catalog. ThemedChart / Line / Area from the design
system; hooks in ui/src/api/queries/admin/serverMetrics.ts. Not yet
browser-verified against a running dev server — backend IT covers the API
end-to-end (8 tests), UI typecheck + production bundle both clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 09:00:14 +02:00
hsiegeln
75a41929c4 chore(gitnexus): sync indexed symbol count
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 1m34s
CI / docker (push) Successful in 1m4s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 41s
SonarQube / sonarqube (push) Successful in 4m54s
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 23:42:26 +02:00
hsiegeln
d58c8cde2e feat(server): REST API over server_metrics for SaaS dashboards
Adds /api/v1/admin/server-metrics/{catalog,instances,query} so SaaS control
planes can build the server-health dashboard without direct ClickHouse
access. One generic /query endpoint covers every panel in the
server-self-metrics doc: aggregation (avg/sum/max/min/latest), group-by-tag,
filter-by-tag, counter-delta mode with per-server_instance_id rotation
handling, and a derived 'mean' statistic for timers. Regex-validated
identifiers, parameterised literals, 31-day range cap, 500-series response
cap. ADMIN-only via the existing /api/v1/admin/** RBAC gate. Docs updated:
all 17 suggested panels now expressed as single-endpoint queries.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 23:41:02 +02:00
hsiegeln
64608a7677 chore(gitnexus): sync indexed symbol count
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 1m18s
CI / docker (push) Successful in 1m4s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 42s
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 23:22:20 +02:00
hsiegeln
48ce75bf38 feat(server): persist server self-metrics into ClickHouse
Snapshot the full Micrometer registry (cameleer business metrics, alerting
metrics, and Spring Boot Actuator defaults) every 60s into a new
server_metrics table so server health survives restarts without an external
Prometheus. Includes a dashboard-builder reference for the SaaS team.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 23:20:45 +02:00
hsiegeln
0bbe5d6623 chore(gitnexus): sync indexed symbol count
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 19:18:49 +02:00
hsiegeln
e1ac896a6e chore(gitnexus): refresh indexed symbol count
Second analyze pass after pushing showed a slightly different symbol
count. Counts-only bump.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 19:17:45 +02:00
hsiegeln
58009d7c23 chore(gitnexus): refresh indexed symbol/relationship counts
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 1m14s
CI / docker (push) Successful in 1m4s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 42s
Auto-bumped by `npx gitnexus analyze --embeddings` after the diagram
refactor landed. No content changes — counts only.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 19:15:08 +02:00
hsiegeln
b799d55835 fix(ui): sidebar catalog counts follow global time range
useCatalog now accepts optional from/to query params and LayoutShell
threads the TopBar time range through, so the per-app exchange counts
shown in the sidebar align with the Exchanges tab window. Previously
the sidebar relied on the backend's 24h default — 73.5k in the sidebar
coexisted with 0 hits in a 1h Exchanges search, confusing users.

Other useCatalog callers stay on the default (no time range), matching
their existing behavior.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 19:15:01 +02:00
hsiegeln
166568edea fix(ui): preserve environment selection across logout
handleLogout explicitly cleared the env from localStorage, forcing the
env switcher modal to re-open on every login. Drop that clear so the
last selected env is restored from localStorage on the next session —
the expected behavior for a personal-preference store.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 19:14:30 +02:00
hsiegeln
f049a0a6a0 docs(rules): capture new DiagramStore method and registry-free lookup
- app-classes: DiagramRenderController by-route endpoint no longer
  depends on the agent registry; points at findLatestContentHashForAppRoute
  and cross-refs the exchange viewer's content-hash path.
- core-classes: document the new DiagramStore method and note why the
  agent-scoped findContentHashForRoute stays for the ingest path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 19:11:45 +02:00
hsiegeln
f8e382c217 test(diagrams): add removed-route + point-in-time coverage
Store-level: assert findLatestContentHashForAppRoute picks the newest
hash across publishing instances (proves the lookup survives agent
removal), isolates by (app, env), and returns empty for blank inputs.

Controller-level: assert the env-scoped /routes/{routeId}/diagram
endpoint resolves without a registry prerequisite, 404s for unknown
routes, and that an execution's stored diagramContentHash stays pinned
to the point-in-time version after a newer diagram is stored — the
"latest" endpoint flips to v2, the by-hash render remains byte-stable.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 19:11:06 +02:00
hsiegeln
c7e5c7fa2d refactor(diagrams): retire findContentHashForRouteByAgents
All production callers migrated to findLatestContentHashForAppRoute in
the preceding commits. The agent-scoped lookup adds no coverage beyond
the latest-per-(app,env,route) resolver, so the dead API is removed
along with its test coverage and unused imports.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 19:02:47 +02:00
hsiegeln
0995ab35c4 fix(catalog): preserve fromEndpointUri for removed routes
Both catalog controllers resolved the from-endpoint URI via
findContentHashForRouteByAgents, which filtered by the currently-live
agent instance_ids. Routes removed between app versions therefore lost
their fromUri even though the diagram row still exists.

Route through findLatestContentHashForAppRoute so resolution depends
only on (app, env, route) — stays populated for historical routes.
CatalogController now resolves the per-row env slug up-front so the
fromUri lookup works even for cross-env queries against managed apps.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 19:01:19 +02:00
hsiegeln
480a53c80c fix(diagrams): by-route lookup no longer requires live agents
The env-scoped /routes/{routeId}/diagram endpoint filtered diagrams by
the currently-live agent instance_ids. Routes removed between app
versions have no live publisher, so the lookup returned 404 even though
the historical diagram row still exists in route_diagrams. Sidebar
entries for removed routes showed "no diagram" as a result.

Switch to findLatestContentHashForAppRoute which resolves directly off
(applicationId, environment, routeId) + created_at DESC, independent of
the agent registry. The controller no longer depends on
AgentRegistryService.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 18:59:43 +02:00
hsiegeln
d3ce5e861b feat(diagrams): add findLatestContentHashForAppRoute with app-route cache
Agent-scoped lookups miss diagrams from routes whose publishing agents
have been redeployed or removed. The new method resolves by
(applicationId, environment, routeId) + created_at DESC, independent of
the agent registry. An in-memory cache mirrors the existing hashCache
pattern, warm-loaded at startup via argMax.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 18:58:49 +02:00
hsiegeln
e5c8fff0f9 docs(HOWTO): document CAMELEER_SERVER_RUNTIME_CERTRESOLVER env var
Added the new Traefik TLS cert resolver setting to the runtime env var
table. Blank default matches how ACME-less dev/local installs want the
`tls.certresolver` label omitted entirely.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 18:22:27 +02:00
hsiegeln
21db92ff00 fix(traefik): make TLS cert resolver configurable, omit when unset
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 1m15s
CI / docker (push) Successful in 1m3s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 42s
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>
2026-04-23 18:18:47 +02:00
hsiegeln
165c9f10e3 feat(deploy): externalRouting toggle to keep apps off Traefik
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 1m26s
CI / docker (push) Successful in 1m5s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 41s
Adds a boolean `externalRouting` flag (default `true`) on
ResolvedContainerConfig. When `false`, TraefikLabelBuilder emits only
the identity labels (`managed-by`, `cameleer.*`) and skips every
`traefik.*` label, so the container is not published by Traefik.
Sibling containers on `cameleer-traefik` / `cameleer-env-{tenant}-{env}`
can still reach it via Docker DNS on whatever port the app listens on.

TDD: new TraefikLabelBuilderTest covers enabled (default labels present),
disabled (zero traefik.* labels), and disabled (identity labels retained)
cases. Full module unit suite: 208/0/0.

Plumbed through ConfigMerger read, DeploymentExecutor snapshot, UI form
state, Resources tab toggle, POST payload, and snapshot-to-form mapping.
Rule files updated.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 18:03:48 +02:00
hsiegeln
ade1733418 ui(deploy): remove Exposed Ports field from Resources tab
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 1m25s
CI / docker (push) Successful in 1m4s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 41s
The field was cosmetic — `containerConfig.exposedPorts` only fed Docker's
`Config.ExposedPorts` metadata via `withExposedPorts(...)`. It never
published a host port and Traefik routing uses `appPort` from the label
builder, not this list. Users reading the label "Exposed Ports" reasonably
expected it to expose their port externally; removing it until real
multi-port Traefik routing lands (tracked in #149).

Backend DTOs (`ContainerRequest.exposedPorts`, `ConfigMerger.intList
("exposedPorts")`) are left in place so existing containerConfig JSONB
rows continue to deserialize. New writes from the UI will no longer
include the field.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 17:51:46 +02:00
hsiegeln
0cf64b2928 fix(audit): exclude env-scoped executions/search from safety-net log
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 1m24s
CI / docker (push) Successful in 1m1s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 37s
The exclusion list still named the legacy flat `/api/v1/search/executions`
URL, which no longer exists — the endpoint moved to env-scoped
`/api/v1/environments/{envSlug}/executions/search`. Exact-match Set
lookup never matched, so every UI search POST produced an audit row.

Switch to AntPathMatcher over a pattern list so the dynamic envSlug is
handled correctly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 17:35:44 +02:00
hsiegeln
0fc9c8cb4c docs(rules): checkpoints live inside Identity grid; HistoryDisclosure retired
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 1m21s
CI / docker (push) Successful in 1m6s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 38s
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 17:15:05 +02:00
hsiegeln
fe4a6dbf24 ui(deploy): remove redundant HistoryDisclosure from Deployment tab 2026-04-23 17:13:45 +02:00
hsiegeln
9cfe3985d0 refactor(ui): route CheckpointsTable via IdentitySection.checkpointsSlot 2026-04-23 17:12:12 +02:00
hsiegeln
18da187960 refactor(ui): checkpoints in-grid styles + drop retired row-list/history CSS 2026-04-23 17:10:42 +02:00
hsiegeln
9c1bd24f16 test(ui): CheckpointsTable covers fragment layout + locale sub-line 2026-04-23 17:08:57 +02:00
hsiegeln
177673ba62 feat(ui): CheckpointsTable emits grid fragment + locale sub-line 2026-04-23 17:03:31 +02:00
hsiegeln
77f5c82dfe feat(ui): IdentitySection accepts checkpointsSlot rendered inside configGrid 2026-04-23 17:01:52 +02:00
hsiegeln
663a6624a7 docs(plan): checkpoints grid row + locale time + remove History (7 TDD tasks)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 16:54:42 +02:00
hsiegeln
cc3cd610b2 docs(spec): checkpoints into identity grid + locale time + remove History
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 16:51:08 +02:00
hsiegeln
b6239bdb6b docs(rules): reflect deployment page polish (upload-in-button, sort/refresh, collapsible checkpoints, DS Select, tab reorder)
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 1m21s
CI / docker (push) Successful in 1m8s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 38s
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 16:16:52 +02:00
hsiegeln
0ae27ad9ed ui(drawer): reorder tabs Config first, default to Config 2026-04-23 16:15:29 +02:00
hsiegeln
e00848dc65 refactor(ui): drawer replica filter uses DS Select 2026-04-23 16:13:54 +02:00
hsiegeln
f31975e0ef feat(ui): checkpoints table collapsible, default collapsed 2026-04-23 16:09:28 +02:00
hsiegeln
2c0cf7dc9c fix(ui): StartupLogPanel — defensive scrollTo + disable buttons while fetching 2026-04-23 16:05:35 +02:00
hsiegeln
fb7b15f539 feat(ui): startup logs — sort toggle + refresh button + desc default 2026-04-23 16:00:44 +02:00
hsiegeln
1d7009d69c feat(ui): useStartupLogs accepts sort parameter (default desc) 2026-04-23 15:58:02 +02:00
hsiegeln
99a91a57be feat(ui): wire JAR upload progress into the primary action button 2026-04-23 15:54:23 +02:00
hsiegeln
427988bcc8 feat(ui): PrimaryActionButton gains uploading mode + progress overlay 2026-04-23 15:49:27 +02:00
hsiegeln
a208f2eec7 feat(ui): useUploadJar uses XHR and exposes onProgress 2026-04-23 15:44:50 +02:00
hsiegeln
13f218d522 docs(plan): deployment page polish (9 TDD tasks)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 15:42:06 +02:00
hsiegeln
900fba5af6 docs(spec): deployment page polish (upload-in-button, sort/refresh, collapsible checkpoints, DS Select, tab reorder)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 15:36:57 +02:00