Skip to content

Changelog

What's new in DBHelm

Every release, documented.

v1.63.4 June 2026 Latest
  • MongoDB monitoring now auto-detects credentials and TLS for non-standard Kubernetes charts
  • Added manual credential & TLS overrides for MongoDB databases that can't be auto-detected
  • More reliable Direct Connect to MongoDB replica sets through an SSH bastion (with SOCKS5 guidance)
  • Deep health checks for direct/VM-connected MongoDB
  • Hid Kubernetes-only diagnostics for direct connections and fixed a spurious upgrade prompt in the MongoDB console
v1.63.3 June 2026
  • Provisioned databases now load monitoring dashboards immediately (no longer wait for the cluster detail page)
  • Provisioned clusters register into monitoring at create time and reconcile to ready automatically
  • Workspace Backups now supports provisioned VM/cloud databases instead of erroring
v1.63.2 June 2026
  • Logs now work for all Kubernetes engines (Postgres, MySQL, Redis, Kafka), not just MongoDB
  • Workspace modules now scope to the selected database instead of showing the whole fleet
  • Cloud-managed databases link straight to the provider log console
v1.63.1 June 2026
  • Fixed spurious 'Upgrade' popups on free pages (Console, Environments, Plan Watch, workspace Alerts)
  • Capability matrix now matches backend: scheduler/logs/alerts shown as 'coming soon' for non-MongoDB engines; Redis backups marked planned
  • Plan Watch is now free (part of the Optimize suite)
  • Multi-organization management gated to DBHelm Platform
  • Dashboard hides empty engine cards; workspace sidebar shows Pro badges
v1.63.0 June 2026
  • Freemium tiers: DBHelm (free) vs DBHelm Platform (paid)
  • Free forever: query, monitoring, advisor, diagnostics, health checks, and BYO-AI — for both registered environments and direct connections
  • Platform features: provisioning, backups & PITR, maintenance, automation, federation, engine migration, and governance
  • Offline Ed25519-signed license keys, activated in Settings; no phone-home
  • Locked features show an upgrade prompt with a clear free-vs-Platform split
v1.62.3 June 2026
  • Fixed k8s-psmdb MongoDB clusters creating no pods — the Percona operator now installs cluster-wide so PerconaServerMongoDB resources in any namespace are reconciled. Added a Reinstall action in Operator Hub.
v1.62.2 June 2026
  • Fixed MongoDB operator (Percona PSMDB) install failing with 'openAPIV3Schema must not be empty' — CRDs now apply via raw JSON so the Kubernetes client no longer strips x-kubernetes-* schema fields.
v1.62.1 June 2026
  • Security: MongoDB shell credentials are now passed over stdin instead of command-line flags, so passwords no longer appear in container process lists.
v1.62.0 June 2026
  • Kubernetes-backed MongoDB (Community & StatefulSet) now uses the full monitoring suite — real-time metrics, replication health, query insights, performance, growth, and more — at parity with Direct Connect.
  • True per-member metrics and node-compare for K8s Mongo replica sets (execs into every replica pod), plus live mongod log analysis via kubectl logs.
  • Authenticated monitoring and object administration over kubectl-exec on auth-enabled clusters (admin credentials and TLS resolved automatically).
  • Structured object administration for MongoDB: create, list, and drop databases, users, and collections from the Objects view.
v1.61.5 June 2026
  • Fixed k8s-psmdb MongoDB clusters stalling on clusters whose default StorageClass isn't named 'standard' (GKE/EKS) — added a Storage class input that defaults to the cluster default
v1.61.4 June 2026
  • Fixed Percona MongoDB operator CRD install failing on large multi-version CRD schemas (use create/replace instead of server-side apply for CRDs)
v1.61.3 June 2026
  • Fixed operator install failing with HTTP 422 (server-side apply force flag) on Kubernetes client v1.x
  • Fixed Percona cluster scale/pause/resume day-2 operations on Kubernetes client v1.x
v1.61.2 June 2026
  • Fixed operator install + day-2 K8s operations failing on Kubernetes client v1.x (HTTP status read from the wrong property)
  • k8s-psmdb managed backups: scheduled backups, PITR, and S3/GCS/Azure object storage
  • vm-mongo-rs backups via Percona Backup for MongoDB (PBM) with point-in-time recovery
  • Authentication enabled by default on k8s-mongo-statefulset and vm-mongo-rs (keyFile + --auth)
  • StatefulSet HA: anti-affinity, resource requests, and PodDisruptionBudget
  • Object administration for Community, StatefulSet, and VM MongoDB clusters
v1.61.1 June 2026
  • Fix Mongo preflight falsely reporting PSMDB operator as installed
  • Operator install: Confirm & Install flow for cluster-scoped CRDs (ackClusterScope)
  • Reject invalid K8s namespace names (e.g. mongodb_server — use hyphens)
  • Wait up to 90s for operator CRD visibility after install on GKE
v1.61.0 May 2026
  • Mongo StatefulSet: RS init Job + admin Secret — replica set ready before status=ready
  • VM Mongo RS: real mongod install over SSH with rs.initiate() and admin user
  • Azure object admin: azure-db-postgres and azure-db-mysql registration fix
  • Mongo backups: k8s-mongo-mongodump adapter for Community + StatefulSet clusters
v1.60.0 May 2026
  • Provision Database sidecar — Atlas-style wizard for MongoDB, PostgreSQL, and MySQL
  • Mongo: PSMDB, Community, StatefulSet, and VM replica sets with preflight + monitoring link
  • PostgreSQL: CloudNativePG, Percona PG, and GCP/AWS/Azure managed cloud
  • MySQL: InnoDB Cluster operator and GCP/AWS/Azure managed cloud
v1.59.0 May 2026
  • Direct Connect monitoring parity: multi-member metrics, perf hours, host metrics over SSH
  • Mongo registration wizard with monitoring readiness panel and Open Monitoring/Advisor links
  • Optional DBHelm Observer on jump boxes (read-only local snapshot, no inbound ports)
  • Advisor: hide Getting Started when a cluster is selected
v1.58.4 May 2026
  • Fix Direct Connect Mongo routing — Monitoring and Advisor use /monitoring/mongo instead of K8s generic API
  • Workspace /db/:id/monitoring and /advisor auto-select direct targets
  • Detect direct Mongo via source/operator; hide K8s-only generic dashboard for Advisor
v1.58.3 May 2026
  • Advisor: Index Advisor on Performance overview; K8s-only Right-Sizing/Cost for Direct Connect
  • Direct Connect: full performance pipeline (logs, indexStats, drop-index, schema) and live member metrics
  • Advisor shell: filtered tabs, in-advisor incident debug, Slow Log SSH/upload UX
  • Monitoring: Query Insights Index Advisor sub-tab and perf→Query Advisor prefill
v1.58.2 May 2026
  • LOCK DEBUG — live currentOp, per-namespace pressure, global lock queues, WiredTiger tickets, and flow control for contention triage
  • COST SAVINGS ADVISOR — cluster-scoped monthly/annual estimates from rate-card spend and right-sizing waste
  • RIGHT-SIZING HISTORY — 14-day utilization patterns, sparklines, and historical advice from periodic snapshots
  • MONITORING TAB CLEANUP — removed Compare, Workload, and Incidents tabs; replication panel embedded in Health Check
  • INCIDENT CONNECTIVITY — mongoK8sExec scalar parsing and multi-pod ping so stale incident banners are less false-positive
v1.58.1 May 2026
  • Advisor: Right-Sizing and Cost Savings tabs; Health Check under Monitoring
  • Incident banner: clearer copy; environment-wide chip only when ≥2 clusters degraded
  • Fleet sidebar: hide Compliance and DB Users until ready
  • Right-Sizing and legacy routes redirect to Advisor
v1.58.0 May 2026
  • Monitoring: Incidents, Compare, and Workload tabs
  • Global freshness chips and sustained-alert drilldowns to queries, realtime, and locks
  • Persisted Metrics presets (Golden, DBA, SRE, Developer) per cluster
  • Cluster A/B compare moved to dedicated Compare tab with overlay charts
v1.57.4 May 2026
  • Advisor incident banner: shorter copy and only Performance / Query / Slow Log / Code tools
  • Open Debug Panel from Advisor links to Monitoring incident-debug for the same cluster
  • Keep-alive router fix (v1.57.3): Console, Monitoring, and Advisor without nested MemoryRouter
v1.57.3 May 2026
  • Fix nested Router crash on Console, Monitoring, Advisor, and all keep-alive workbench modules
  • Keep-alive panes use Routes location= on the root BrowserRouter instead of MemoryRouter
  • Regression tests cover console, monitoring, advisor, and cluster paths
v1.57.2 May 2026
  • Fix Monitoring and Advisor crash (nested Router error on fleet navigation)
  • Fleet Monitoring and Advisor use main app router; workspace Advisor keep-alive route added
v1.57.1 May 2026
  • Advisor module: dedicated Performance, Query, Slow Log, and Code advisor tabs under Observability
  • Monitoring links to Advisor; legacy performance URLs redirect automatically
  • MongoDB workspace includes Advisor next to Monitoring
v1.57.0 May 2026
  • Mongo Performance Advisors: Query, Slow Log, and Code Advisor under Monitoring
  • Live explain + index recommendations, slow-log batch review, and load-from-cluster-logs
  • AST code extraction for JavaScript/TypeScript/Python with optional org-shared advisor history
  • $lookup join-key index hints and optional AI narratives (Settings → AI)
v1.56.1 May 2026
  • Mongo Monitoring & DB Studio — GA for self-hosted MongoDB (PSMDB, K8s-managed, Direct Connect)
  • Explorer is strictly read-only: comprehensive DDL/DML blocklist enforced on server and client
  • No inline document edit, Safe Ops shortcuts, or create-index from Explorer — use Safe Ops (DML) and Indexes (DDL) tabs
  • Direct Connect: full DB Studio over the official driver with a curated mongosh subset (find, aggregate, explain, etc.)
v1.56.0 May 2026
  • Mongo DB Studio: paginated Explorer (Next / Load more), Schema panel, BSON field editor, workbench tab persistence
  • Monitoring → Studio deep links on slow ops and Performance Advisor index rows
  • Explain plan: one-click Create index + Re-explain; Pipeline linter; org policies (system.*, $out/$merge, max limit)
  • Saved queries + searchable history; Bulk import/export; staging vs prod Compare across workbench connections
v1.55.9 May 2026
  • Fleet workbench (renamed from Main): fleet-wide Dashboard, All Databases, Environments stay in the Fleet tab
  • Cluster workbenches open /db/:id with Console, Monitoring, Backups, Optimize, and all per-DB modules
  • True keep-alive: switching workbench tabs never unmounts Console — running queries continue in the background
  • Close a cluster workbench tab (×) to tear it down; Fleet workbench is always available
v1.55.8 May 2026
  • Renamed Sessions → Workbenches: Fleet = fleet-wide modules, cluster workbenches = per-DB workspace
  • New workbench from cluster cards opens /db/:id with Console, Monitoring, Backups, Optimize, and more
  • Fleet sidebar (Dashboard, All Databases, Environments) switches to Fleet workbench automatically
  • Parallel cluster workbenches keep Console queries alive when you switch tabs
v1.55.7 May 2026
  • Workbench sessions: Main session by default + up to 8 parallel sessions with tab switcher in header
  • Switch sessions without aborting Console queries — inactive sessions stay mounted in keep-alive panes
  • Open cluster in new session from All Databases cards and Console grid (Console / Monitoring / Dashboard)
  • Rename any session; cluster-opened sessions default to cluster name
v1.55.6 May 2026
  • Real Time slow ops: per-query resource share bars (est. CPU, I/O, memory) when multiple queries run
  • Collects currentOp throughput, lock wait, and tracked memory bytes (MongoDB 8.3+) for attribution
  • Mini Real Time strip shows the same per-query resource breakdown in Console
v1.55.5 May 2026
  • Console mini Real Time strip: live CPU, WT cache, slow op count while a query runs — plus 5 min after heavy queries
  • Namespace-matched slow ops in the strip with Kill + Full Monitoring (opens new tab)
  • Monitoring deep links: /monitoring?cluster=…&tab=realtime&namespace=db.coll pre-filter Real Time slow ops
  • Resource Impact banner Open Monitoring opens in a new tab so Console session stays alive
v1.55.4 May 2026
  • Explorer Stop query: kill matching active ops via killOp while a query runs; elapsed timer turns amber/red at 10s/30s
  • Post-run Resource Impact banner: severity, docs examined, COLLSCAN flag — Open Monitoring, explain plan, tighten guard actions
  • Session execution history panel in IntelliShell with re-run and impact dots
  • Monitoring Real Time: Kill operation button on expanded active ops (PSMDB + Direct Connect)
v1.55.3 May 2026
  • COLLSCAN confirm dialog: when policy is Warn or Allow, Explorer runs explain preflight and shows impact analysis (docs examined, scan ratio, severity) before Run
  • Proceed / Cancel — users must explicitly accept collection scan risk; cancelled queries logged in shell output
  • Block policy now includes docs examined / returned counts in the rejection message
v1.55.2 May 2026
  • Compass-style multi-cluster workspace: Console grid opens one cluster; use Connections or the top bar to add more (up to 4)
  • Session-scoped connections — no localStorage bleed when returning to Console and opening a different cluster
  • Connections panel: explicit connect/disconnect per fleet cluster (PSMDB, Direct Connect, K8s Mongo)
v1.55.1 May 2026
  • Fix Add cluster in DB Studio: list all PSMDB clusters from fleet (/maintenance/clusters), not only Console-registered databases
  • Add cluster dropdown renders via portal (no overflow clipping); includes Direct Connect Mongo targets
v1.55.0 May 2026
  • Mongo Explorer query guard: server-enforced maxTimeMS (3 min default) on find/aggregate/count; COLLSCAN policy block / warn / allow with explain preflight
  • Admin → Settings: Mongo Explorer query guard panel for super admins (timeout + COLLSCAN policy); Explorer banner shows active policy read-only
  • Multi-cluster DB Studio: up to 4 connection tabs (PSMDB, Direct Connect, K8s Mongo) — cross-cluster queries without leaving Console; tabs persist in localStorage
v1.54.0 May 2026
  • K8s PSMDB sharding: GET /monitoring/:clusterId/sharding — balancer, chunks, migrations (parity with Direct Connect)
  • Direct Connect: $planCacheStats in background perf scans; query-insights log fallback when profiler hangs (profile → log → cache)
  • Host metrics time-series: disk read/write KB/s, load, disk use %, memory — via SSH on Direct VMs and pod exec on K8s (Metrics → Hardware charts)
v1.53.0 May 2026
  • Direct Connect Performance → System Config: MongoDB + OS recommendations (OS via SSH when tunnel enabled)
  • Direct Connect Growth: per-collection index analysis with unused/redundant/duplicate index suggestions
  • Direct Connect logs: GCP Cloud Logging (stackdriver) and Azure Monitor Log Analytics for VM mongod logs — configure under Direct Connect → Edit
v1.52.0 May 2026
  • Product positioning: MongoDB monitoring targets self-hosted deployments you control (Kubernetes PSMDB or Direct Connect) — not vendor DBaaS like Atlas or DocumentDB
  • Direct Connect parity: overview historical metrics (/history), daily storage_snapshots with growth breakdown, topology visualization, and deeper sharding (config servers, sharded DBs, recent migrations)
  • Direct Connect UX: Atlas removed from picker; API rejects mongodb-atlas/documentdb; log settings for SSH, CloudWatch, or upload on your infrastructure
v1.51.0 May 2026
  • Direct Connect Mongo log analysis: SSH mongod.log tail, AWS CloudWatch, and log file upload — same analyzer as K8s monitoring
  • Direct Connect settings UI: configure log source (SSH path, CloudWatch region/group, upload-only for Atlas) when adding or editing a connection
  • Direct Connect monitoring parity: incident debug panel, growth node-compare, sharding status, PBM on incident banner, background perf scans + rescan
v1.49.0 May 2026
  • Direct Connect Mongo monitoring: TCP routes for dashboard, realtime, replication, query insights, performance, and growth
  • Background metric and extended snapshots (30s / 5m) with incident-resilient cache fallbacks for v1.47 panels
  • Growth history and v147-incident-meta polling for Direct Connect replica sets
v1.48.0 May 2026
  • FULL INCIDENT RESILIENCE FOR ALL MONITORING PANELS — v1.47.0 shipped 4 new panels (Replication, Index Advisor, Collections, Locks) that closed major coverage gaps. But they went directly through mongosh — so during a real incident when the database is unresponsive they would just time out. v1.48.0 brings those 4 panels up to the same incident-resilient bar as the v1.42-46 panels: every endpoint now uses the dispatcher pattern with cached snapshot + log + FTDC fallback. The Monitoring Dashboard is now truly usable for triage when mongod is hung.
  • EXTENDED SNAPSHOTS — metricsCollector gained a new 5-minute "extended snapshot" capture that writes the heavier-weight data the 4 panels need (full rs.status, lockStats, cursorStats, indexInventory, collStats) into a new extended_snapshots table. Done in a single mongosh call per cluster per 5 min, so it adds negligible load. During incidents this cache is the operator's lifeline — the dashboard shows the last successful capture with a freshness badge ("CACHED · 3m ago") instead of a blank panel.
  • REPLICATION HEALTH — now has a 3-source dispatcher: (1) live mongosh rs.status() with 8s timeout, (2) cached rs.status from extended_snapshots, (3) mongod log parsing for election / stepdown / heartbeat events via new pure replicationLogParser module. Operators see oplog lag per member + oplog window + election history even when the database itself is hung. Election events come from kubelet-captured mongod stdout log — the most resilient source possible.
  • INDEX ADVISOR — dual-source dispatcher with separate source chips for "indexes" and "queries". Existing indexes: mongosh (15s) → cached indexInventory fallback. Slow queries: mongod log (already incident-resilient). During incidents the advisor still suggests indexes from the last successful index inventory + current log-based slow queries. Each suggestion remains valid even on stale index data.
  • COLLECTION STATS — cached fallback for the heavy per-collection stats walk. During incidents the dashboard shows the last successful snapshot (taken within the last 5 min) with the staleness badge. Workload heatmap (already log-based) remains fully live.
  • LOCKS & CURSORS — cached fallback for lock + cursor stats. Cursor leak detection (already from metric_snapshots history) remains fully live and incident-resilient. During incidents the operator can still see "the last known lock contention picture" + ongoing leak trend.
  • REPLICATION LOG PARSER — new pure module services/monitoring/replicationLogParser.ts parses MongoDB's structured JSON logs for replication events: state transitions (PRIMARY ↔ SECONDARY — id 21358/21392), elections started (id 4615648) and won (id 21215), stepdowns (id 21405), heartbeat failures (id 21379), sync source changes (id 21390). Also handles legacy 4.0-style plain-text log lines as a fallback. De-dupes near-duplicate state transitions within 1s (boot-up noise). 24 unit tests covering every event type + edge cases.
  • SOURCE CHIPS — new SourceChip component shows data provenance + staleness inline in every v1.47 panel header. Colour-coded: emerald LIVE (mongosh), amber CACHED (snapshot + age), blue LOG (mongod log), violet FTDC, cyan K8S, red NO DATA. Tooltip explains why fallback was used (e.g. "mongosh: timed out after 8s"). Operators can tell at a glance whether the data they're acting on is fresh or stale.
  • SCHEMA MIGRATION — new extended_snapshots table with rs.status + lockStats + cursorStats + indexInventory + collStats JSON columns. Indexed by (perconaClusterId, ts DESC) for fast latest-snapshot lookup. Old metric_snapshots table unchanged. 15-day retention pruning extended to the new table.
  • TESTS — 24 new replicationLogParser tests (state transitions / elections / stepdowns / heartbeat failures / sync source changes / legacy format / de-duplication / window filtering). 6 new frontend tests for source chips across all 4 v1.47 panels (LIVE / CACHED with age / LOG / dual-chips for index advisor). Backend: 1785 → 1809 (+24). Frontend: 466 → 472 (+6). Total: 2251 → 2281.
  • NO BREAKING CHANGES — all changes additive: new extended_snapshots table, new optional response fields (_source, _staleSeconds, _incidentMode, _fallbackReasons), new SourceChip component. v1.47.0 frontends still work with v1.48.0 backend (the new chips just don't appear). v1.47.0 backend still works with v1.48.0 frontend (chips render as undefined and panel hides them).
  • OPERATOR EXPERIENCE — the headline change is psychological: previously, hitting an incident on a v1.47 tab would show a generic error. Now it shows the LAST KNOWN GOOD DATA with a clear "CACHED · 4m ago" badge — the operator can immediately reason about what the cluster looked like just before the incident started, which is exactly what triage needs.
  • CI — v1.48.0 is a minor release (.0 tag), macOS DMG rebuilds automatically.
v1.47.0 May 2026
  • COMPREHENSIVE MONITORING EXPANSION — v1.42-46 made the existing monitoring incident-resilient and added the auto-correlated narrative. v1.47.0 fills 4 of the 6 major coverage gaps identified in the v1.46 audit: replication health (oplog lag + window + elections), index advisor (Atlas Performance Advisor parity), per-collection stats + workload heatmap, lock contention + cursor leak detection. Four new dedicated tabs in the Monitoring page.
  • REPLICATION HEALTH PANEL — the #1 most-common SEV1 in real MongoDB ops. Surfaces per-member oplog lag in seconds (with severity classification: none / low / high / critical), per-member heartbeat freshness (>30s = network partition warning), oplog window length AND projected drain time at current write rate (healthy >24h, short 6-24h, critical <6h), election history with relative timestamps, sync source per secondary, and aggregated warnings ("mongo-1 is critically behind (600s lag) — risk of falling off oplog").
  • INDEX ADVISOR PANEL — parity with MongoDB Atlas Performance Advisor. Parses slow-query log, classifies each query's filter into ESR categories (Equality / Sort / Range), builds an ESR-ordered compound index suggestion, dedupes against existing indexes (including compound-prefix coverage detection), ranks suggestions by impact (total slow-query time addressed), and emits copy-pasteable shell commands. Plus dedicated COLLSCAN warnings for queries hitting no index at all. Severity: high (>60s of slow-query time), medium (>10s), low.
  • COLLECTION STATS + WORKLOAD HEATMAP — closes the "which collection is the problem?" question. Per-collection: doc count, logical + storage size, avg doc size, index count + size, largest index by name, WiredTiger compression ratio, fragmentation/bloat detection (reusable bytes ratio with severity classification + prescriptive recommendation: "Run db.events.compact() to reclaim 7.45 GB"). Plus a workload heatmap matrix showing slow-query activity per namespace in 5-minute buckets over the last 15 minutes — cell intensity = total slow-query duration in that window. Top 15 hottest namespaces highlighted.
  • LOCKS & CURSORS PANEL — per-resource lock contention breakdown (Global / Database / Collection / Mutex) with wait ratio percentage and avg wait time per acquisition. Severity classification (none < 1% waits, low < 5%, medium < 15%, high otherwise). Cursor metrics: open total, pinned, noTimeout (flagged separately as risk), cumulative timed-out. Cursor leak detection via linear regression on recent metric snapshot history — reports growth rate per minute with confidence (low/medium/high) and a human-readable reasoning paragraph ("Open cursor count is trending up at ~10.5/min over 600s (monotonicity 90%). Likely application not closing cursors.").
  • BACKEND — 4 new pure helper modules totalling ~1,200 lines (replicationHealthHelpers.ts, indexAdvisorHelpers.ts, collectionStatsHelpers.ts, lockMetricsHelpers.ts), all dependency-free and 100% unit-tested. 4 new REST endpoints under /api/monitoring/<cluster> using the established dispatcher pattern (aggressive mongosh timeouts, log fallback for slow-query data, snapshot history for cursor leak detection). Routes share the same incident-mode flag conventions as v1.42-46 endpoints.
  • FRONTEND — 4 new self-contained panel components (ReplicationHealthPanel, IndexSuggestionsPanel, CollectionStatsPanel, LockMetricsPanel) wired into MonitoringPage as new tabs (Replication / Index Advisor / Collections / Locks & Cursors). Each panel has its own loading / error / empty / data states, refresh button, and severity-coloured banners. IndexSuggestionsPanel includes copy-to-clipboard for each shell command with toast confirmation. CollectionStatsPanel includes sortable columns + interactive workload heatmap with hover tooltips.
  • TESTS — 126 new pure-helper tests covering every detector's positive + negative + edge cases. Replication: 34 tests (state-code mapping, lag classification across 4 severities, oplog window severity vs projected window worst-of, election history sorting, missing-primary handling, clock-skew clamping, arbiter no-lag). Index advisor: 35 tests (ESR ordering, $eq/$in/$gt/$gte/$exists/$regex classification, compound index PREFIX coverage detection, direction-mismatch non-coverage, impact ranking, COLLSCAN aggregation, ESR reasoning text, example query capping). Collection stats: 29 tests (byte formatting across all units, bloat severity classification, largest-index identification, workload heatmap bucketing, top-N namespace ranking, custom bucket sizes). Lock metrics: 28 tests (all 4 lock modes, severity classification, sorting by wait micros, cursor leak detection on flat/decreasing/increasing/noisy timeseries, noTimeout flagging). Plus 17 frontend panel tests covering render + interaction + empty/error/data states + copy-to-clipboard. Backend: 1659 → 1785 (+126). Frontend: 449 → 466 (+17). Total: 2108 → 2251.
  • COVERAGE GAPS REMAINING — honest scorecard. v1.47.0 closes 4 of 6 gaps identified in the v1.46 audit. Still NOT covered: sharded cluster telemetry (balancer status, chunk distribution, mongos health — deferred to v1.48.0; needs a sharded test cluster), PBM backup health (deferred to v1.49.0; needs PBM integration design). Together with the existing incident-resilient monitoring + auto-correlated narrative, v1.47.0 brings DBHelm to ~85% coverage of common diagnostic scenarios.
  • NO BREAKING CHANGES — 4 new tabs are purely additive. New routes are mounted at /api/monitoring paths that don't collide with existing endpoints. Existing tabs unchanged. Pre-v1.47.0 frontends still work (new tabs simply not visible until upgrade).
  • CI — v1.47.0 is a minor release (.0 tag), macOS DMG rebuilds automatically.
v1.46.0 May 2026
  • AUTO-CORRELATED INCIDENT NARRATIVE — v1.42-45.1 made every monitoring source incident-resilient (kubelet vitals, K8s events, last snapshot, what-changed diff, slow queries from log, FTDC per-second). v1.46.0 stitches them together. The Incident Debug Panel now opens with a prominent banner that READS THE TIMELINE FOR YOU: severity badge, root-cause hypothesis with confidence score, 3-5 sentence narrative with relative-time notation ("T-6m: mongo-0 OOMKilled. T-2m: cache pressure peaked 98%. now: query burst 12 in 60s."), and an expandable full timeline + reasoning. Operators get the story instead of building it.
  • WHY THIS MATTERS — v1.42-45.1 closed the data-availability gap during incidents (you have all the right signals even when mongod is hung). v1.46.0 closes the COGNITIVE-LOAD gap. Real-world incidents are stressful; mentally stitching K8s events + kubelet pressure + snapshot deltas + slow-query bursts + FTDC samples + replication state into a story takes minutes. The narrative banner does it in milliseconds and shows its work — every claim maps to a concrete signal in the timeline below.
  • BACKEND — new pure module services/monitoring/narrativeBuilder.ts (~600 lines). Detection rules: pod-lifecycle (OOMKilled, CrashLoopBackOff, restart), K8s events (FailedScheduling, Evicted, Unhealthy with severity classification), resource pressure (CPU/mem >90% sustained windows, per-pod), connection storms (>50% jump within 30s window with de-dupe), cache pressure (>90% sustained), replication state changes (PRIMARY ↔ SECONDARY), slow query bursts (≥5 in 60s with namespace aggregation). Each detector returns TimelineEvent[] with severity classification. Top-level buildIncidentNarrative() runs all detectors, sorts the timeline ascending, and infers root cause.
  • ROOT-CAUSE HEURISTICS — 8 ordered patterns: (1) OOMKilled → memory exhaustion (95% confidence), (2) sustained 95%+ memory → imminent OOM (70%), (3) cache pressure + slow queries → working set > RAM (85%), (4) connection storm + slow queries → connection-driven overload (80%), (5) connection storm alone → client leak/retry storm (70%), (6) replica state change → election/failover (75%), (7) cache pressure alone → working set near limit (60%), (8) multiple slow-query bursts → query regression (55%). Empty signals → honest "no clear pattern" with confidence 0. Each hypothesis includes prescriptive remediation (increase memory limit, drop unused indexes, audit connection lifecycle, etc.).
  • NARRATIVE RENDERING — picks the top 3 events by severity + recency + diversity (avoids picking 3 of the same category). Renders with relative-time formatter (T-Ns / T-NmSs / T-NhMm / "now") anchored on the latest event timestamp by default. Bold-markup support (**text**) for the root-cause emphasis. Healthy clusters get an honest "no incident-level signals detected; cluster looks healthy" message instead of fabricating drama.
  • FRONTEND — new NarrativeBanner component embedded at the top of IncidentDebugPanel. Severity-coloured (blue/amber/orange/red), critical-severity uses red border. Top line: "Incident Summary" + severity badge + root-cause chip ("Likely cause: memory exhaustion (95% confidence)"). Body: 3-5 sentence narrative with bold markup. Expandable disclosures: "View full timeline (N events)" shows every detected event with relative time, "Why this hypothesis?" shows the full reasoning paragraph. Self-contained relative-time formatter mirrors the backend.
  • NEVER FABRICATES — design principle. Every event in the narrative timeline maps to a concrete data point from the upstream sources (K8s API, kubelet, FTDC files, mongod logs). The narrative paraphrases what the timeline already shows; it doesn't invent claims. The reasoning paragraph for each root cause cites which signals corroborate it. Operators can audit the narrative by clicking through to the timeline.
  • TESTS — 57 new pure-helper tests covering: every detector's positive + negative + edge cases (OOMKilled detection, CrashLoopBackOff, K8s severity classification, resource-pressure window grouping by pod with custom thresholds, connection storm severity tiers + de-dupe, cache pressure ongoing flag, replica state transitions, slow query burst aggregation across namespaces with multiple bursts), all 8 root-cause patterns + their priorities + empty-input handling, relative-time formatter across the full range (now / seconds / minutes / mins+secs / hours / hours+mins / future T+), and 7 end-to-end builder scenarios (OOM, cache+slow-query, connection-storm, custom nowMs, narrative-length cap, sorted timeline, max-severity calculation). Plus 4 frontend tests for the NarrativeBanner (renders with severity+root-cause, healthy-cluster message, graceful absence when narrative field missing, severity colour matching). Backend: 1602 → 1659 (+57). Frontend: 445 → 449 (+4). Total: 2047 → 2108.
  • NO BREAKING CHANGES — narrative field is additive on /incident-debug response. Pre-v1.46.0 frontends just don't see the banner. Backend renders narrative from data already collected; no new K8s API calls, no new mongod queries, no extra latency. The banner can be omitted entirely (data.narrative undefined) and the panel still works.
  • CI — v1.46.0 is a minor release (.0 tag), macOS DMG rebuilds automatically.
v1.45.1 May 2026
  • FTDC PER-SECOND DELTA DECODER — v1.45.0 shipped reference-sample-only extraction (one sample per ~5 min chunk) because per-second reconstruction needed careful handling of MongoDB's delta encoding. v1.45.1 closes that gap: the on-disk FTDC binary files are now decoded into full per-second time series. Where v1.45.0 gave you ~12 samples for an hour-long incident, v1.45.1 gives you ~3600. Same kubelet-exec data path — same incident resilience — dramatically more granular.
  • DELTA FORMAT IMPLEMENTATION — from MongoDB src/mongo/db/ftdc/util.h + the mongo-tools/ftdc Go reference. Each chunk's decompressed payload is: reference sample BSON, then int32 metricCount + int32 sampleCount, then a stream of uint64 varints. Layout is metric-major (all sampleCount deltas for metric 0, then for metric 1, etc.). RLE-of-zeros: when a varint is 0, the NEXT varint is the count of additional zeros (compresses stable counters from 300 bytes to 2 bytes per metric).
  • SIGNED INT64 INTERPRETATION — mongod encodes negative deltas (gauges going down, like "available connections") via uint64 wraparound: -200 becomes (2^64 - 200) on the wire. v1.45.1 reinterprets any varint with the high bit set as signed int64, so cumulative sum works in normal bigint arithmetic without overflow correction. All real-world mongod metrics fit in int63 so this never collides with legitimate large positive values.
  • BSON-ORDER REFERENCE-SAMPLE FLATTENING — walk the parsed reference BSON document depth-first in document/array key insertion order (matching mongod's metric extraction). Numeric/Date/Boolean leaves become metrics; strings, ObjectIds, BinData are skipped. Floats are truncated to int64 (mongod's convention). Path indexing matches the delta stream's metric ordering.
  • DEFENSIVE FALLBACK — if the delta decoder throws on any chunk (truncated stream, varint overflow, RLE overrun, metric-count mismatch), that chunk falls back to reference-sample-only extraction and the response notes which chunks fell back. The whole panel never breaks because of one corrupt or unfamiliar chunk. Frontend shows "EXPERIMENTAL" badge when full per-second is active and a per-chunk fallback counter when partial.
  • ROUNDTRIP TEST CORPUS — since we don't have a guaranteed-stable real FTDC corpus across all mongod versions, v1.45.1 builds a SYNTHETIC encoder using the exact same BSON library mongod uses to write FTDC files. Every test encodes → decodes → verifies equality. 36 new tests cover: varint roundtrip across the int64 range, BSON-order traversal of nested documents/arrays/dates/booleans, signed-int64 negative-delta handling, RLE compression of stable counters (50-zero run → 2 bytes), mongod 4.0/5.0/6.0/7.0 schema variations, multi-metric mixed delta patterns, full chunk roundtrip with realistic mongod connection-storm progression, sample-period configuration, and graceful failure on every corruption mode.
  • BACKEND ROUTE — /api/monitoring/<cluster>/incident-debug now requests includeTimeSeries=true with maxSamples=600 (10 min @ 1Hz). Response includes ftdc.timeSeriesEnabled flag (true when ALL chunks delta-decoded successfully) and stats.chunksDeltaDecoded / chunksFellBack counters. Per-chunk fallback is invisible to the operator unless they look at the stats line.
  • FRONTEND PANEL — IncidentDebugPanel's FTDC table now scrolls (max-height 24rem, sticky header) since per-second mode produces up to 600 rows. Caps display to most recent 100 for browser perf. Shows "PER-SECOND · EXPERIMENTAL" violet badge when timeSeriesEnabled=true. Shows amber "N chunks fell back" counter when per-chunk fallback occurred (e.g. unfamiliar mongod schema).
  • TESTS — 36 new pure-helper tests for the delta decoder. Backend: 1566 → 1602 (+36 covering readVarint/writeVarint roundtrip across int64 range, flattenReferenceSample BSON-order traversal, decodeDeltaMatrix with no-zeros/explicit-zeros/long-RLE/all-zero/negative/truncated/RLE-overrun cases, reconstructValueMatrix cumulative sum, full chunk roundtrip with simple counters/heavy-RLE/mixed patterns, defensive null returns on type/parseError/metric-count-mismatch, end-to-end pickIncidentMetricsTimeSeries with realistic mongod connection-storm chunk, custom sample-period, and pickIncidentMetricsFromSample with curated path lookups). Frontend: 443 → 445 (+2: experimental badge appears when timeSeriesEnabled=true, fall-back counter appears when chunksFellBack > 0). Total: 2009 → 2047.
  • NO BREAKING CHANGES — backend response is additive: timeSeriesEnabled flag and chunksDeltaDecoded/chunksFellBack stats are new optional fields. Pre-v1.45.1 frontends still work (just don't see the experimental badge). Pre-v1.45.0 frontends still work (FTDC section is hidden if the field is absent). Decoder failure on any chunk falls back to v1.45.0 behaviour invisibly.
  • WHY WE STILL SAY EXPERIMENTAL — without a corpus of real FTDC files from production clusters across mongod 4.0/5.0/6.0/7.0/8.0 to validate against, we can't guarantee 100% correctness. Synthetic roundtrip tests exercise the format spec but can't catch a mongod version that emits BSON in a slightly different traversal order than ours. Operators get the per-second view + an explicit "if you spot anomalies, please report" note. Production deployments get the v1.45.0 reference-sample fallback automatically when anything looks off.
v1.45.0 May 2026
  • FTDC BINARY FILE PARSER — the LAST big gap in incident-time observability is closed. v1.42-44 made every monitoring tab survive a mongod hang via aggressive timeouts, log fallback, kubelet vitals, and what-changed diffs. v1.45.0 adds the ONLY mongod metric source that's truly independent of the query engine: the on-disk FTDC binary files at /var/lib/mongo/diagnostic.data/. Mongod's diagnostic thread writes them every 1 second regardless of whether the database is responsive — perfect for incident debugging.
  • WHY THIS MATTERS — every other "database" data source we use (mongosh, getDiagnosticData admin command, Prometheus mongodb_exporter) goes through the query engine. When the query engine is hung, all of them stop responding. FTDC files are different: they're written by a SEPARATE thread on its own scheduler. Even during a complete query-engine deadlock, FTDC keeps growing. We read the files via kubectl exec (kubelet, not the database) so we get incident-time mongod metrics that no other source can provide.
  • BACKEND — new pure parser services/monitoring/ftdcFileParser.ts (250 lines). Walks the FTDC file format: stream of length-prefixed BSON documents, each either type=0 metadata or type=1 metric chunk. For type=1, decompresses the data field (zlib over BSON-wrapped binary), extracts the reference sample (first sample in the chunk's ~300-sample series), and reports metricCount + sampleCount for future delta reconstruction. Per-chunk error isolation — a corrupt chunk doesn't poison the whole file.
  • BACKEND — new file reader services/monitoring/ftdcFileReader.ts. Two-step kubectl exec: (1) ls -1t to find the latest FTDC file, (2) base64 -w 0 to safely transport binary bytes through the kubectl exec stdout pipeline. base64 encoding avoids the binary-corruption gotcha some K8s API versions have when raw bytes hit TTY layers.
  • CURATED METRIC EXTRACTION — pickIncidentMetrics() pulls the incident-relevant subset from each reference sample: connections (current/available/totalCreated), opcounters (query/insert/update/delete/getmore/command), replica state (with myState→human-name mapping), WiredTiger cache (used/max bytes + pages evicted), network IO totals, globalLock active clients (readers/writers). Defensive against missing fields across mongod 4.0/5.0/6.0/7.0 schema differences.
  • INCIDENT DEBUG PANEL EXTENSION — new "FTDC samples" section in the IncidentDebugPanel (v1.44.0). Shows per-chunk samples in a table: sample time, replica state badge (PRIMARY green / SECONDARY blue / other amber), connection count, opcounter sum, active readers/writers from globalLock, cache used % (red ≥90%, amber ≥75%). Plus stats line ("12 chunks · 512 KB read") and the v1.45.0 limitation note that says "per-second reconstruction arrives in v1.45.1".
  • HONEST SCOPE — v1.45.0 ships REFERENCE-SAMPLE-ONLY extraction (one sample per ~5 min chunk). FTDC chunks contain ~300 samples encoded as deltas (variable-length zigzag varints, RLE-compressed runs of zeros, mapped to a flattened metric-path index). Full per-second delta reconstruction needs a real FTDC test corpus to validate against and is deferred to v1.45.1. Even reference-sample-only is 6× better than the metricsCollector's 30s polling AND it works during hangs when the polling stops.
  • TESTS — 19 new pure-helper tests for the FTDC parser using SYNTHETIC FTDC documents built from scratch with the BSON library mongod uses to write them. Covers: BSON envelope walker (multi-doc, empty, truncated, corrupted), type=0 metadata parsing, type=1 metric chunk decompression + reference sample extraction, metricCount/sampleCount trailer parsing, error isolation per chunk, defensive null handling for missing fields, replica-state code mapping, mongod 4.0→newer schema variations. 5 new frontend tests for the FTDC section: render with samples, warning surface, empty placeholder, cache-pressure red threshold, SECONDARY badge color. Backend: 1547 → 1566 (+19). Frontend: 438 → 443 (+5). Total: 1985 → 2009.
  • NO BREAKING CHANGES — the new FTDC section is additive on /api/monitoring/<cluster>/incident-debug. Pre-v1.45.0 frontends just don't see the new section. Backend FTDC reader fails gracefully with a warning if the diagnostic.data directory doesn't exist (custom dbPath, FTDC disabled, exec permission missing).
  • CI — v1.45.0 is a minor release (.0 tag), macOS DMG rebuilds automatically. Builds run on the public-repo unmetered Actions allowance until the billing cycle resets next month.
v1.44.0 May 2026
  • INCIDENT DEBUG PANEL — v1.42.0 made Query Insights survive incidents. v1.43.0 extended that to all Monitoring tabs. v1.44.0 adds the dedicated debug surface operators actually need DURING the incident: ONE panel showing every piece of data that's still observable when mongod is hung. New "Incident Debug" tab opens via a button in the page-level Incident Mode banner.
  • WHAT THE PANEL SHOWS — 6 sections, all from sources independent of the mongod query engine: (1) Container vitals (CPU/memory per pod, kubelet metrics-server, with pressure-detection badge when any container > 90% of limit); (2) Pod status (ready / restartCount / lastTerminationReason — OOMKilled jumps out red); (3) Last successful mongod snapshot WITH FRESHNESS BADGE ("47s ago" / "5m ago" / "2h ago" — tells you WHEN the hang started); (4) What changed in the last ~5 min — diff between two metric_snapshots SQLite rows showing connection spikes, opcounter changes, cache pressure, replica state transitions; (5) Recent K8s events filtered to incident-relevant ones (Warnings + interesting Normals like Killing/Started/Scheduled, last 15 min); (6) Slow queries from mongod stdout log (kubelet-captured, works when query engine is hung).
  • PHILOSOPHY — every monitoring tool we know shows you the same dashboards in degraded mode that worked when things were fine. The Incident Debug Panel inverts this: when things are broken, show DIFFERENT data — specifically the data that's still trustworthy. CPU pressure from kubelet is more useful during a hang than a 60-second-old "current connections" number from mongosh.
  • BACKEND — new GET /api/monitoring/<cluster>/incident-debug endpoint. Fans out 5 parallel calls (getPods + getMetrics + getEvents + 2x metricSnapshots query) plus a best-effort getPodLogs with 5s timeout for slow queries. None of them touch mongosh. Pure helper module services/monitoring/incidentDebugHelpers.ts factors out the data-shaping (parseSnapshot, diffSnapshots, filterIncidentEvents, summariseVitals, summarisePodStatus, computeFreshness) so the route stays thin and the helpers are unit-testable.
  • COLLECTOR FREQUENCY — metricsCollector default interval halved from 60s → 30s. Finer granularity matters during incidents because the gap between "last successful sample" and "the moment things broke" is what tells the operator WHEN the degradation started. 30s is still cheap enough to run continuously per cluster.
  • FRONTEND — new IncidentDebugPanel component. Wired to MonitoringPage as a new tab ('incident-debug'). The page-level Incident Mode banner from v1.43.0 gained an "Open Debug Panel →" button that switches to the tab. Shareable URL, closeable without losing other tab state. Each section answers ONE diagnostic question; pressure / OOMKilled / restartCount jump out in red so the operator's eye lands on the actionable bits first.
  • WHAT-CHANGED DIFF — the most subtle improvement. The /incident-debug endpoint reads TWO metric_snapshots rows: the most recent one + one from ~5 min before. The pure diffSnapshots helper computes per-field deltas with thresholds (10% for connections, 25% for opcounters, 5% for cache hit rate) and emits human-readable highlights: "connections.current ↑ +4400% (100 → 4500)", "Replica state changed: PRIMARY → SECONDARY". This surfaces the GRADIENT that caused the incident, which a single snapshot can't.
  • TESTS — 32 new backend pure-helper tests (parseSnapshot defensive parsing, diffSnapshots threshold logic + replica-state transitions, filterIncidentEvents window + Warning/Normal filtering, summariseVitals peak-across-timeline + pressure detection, summarisePodStatus container disambiguation + lastTerminationReason, computeFreshness time formatting). 8 new frontend mount tests for IncidentDebugPanel covering: healthy state, active incident with pressure + OOMKilled + slow queries, cold-start (no snapshot), parse error rendering, slowQueryError inline surfacing, refresh, close button, error response. Backend: 1515 → 1547 (+32). Frontend: 430 → 438 (+8). Total: 1945 → 1985.
  • NO BREAKING CHANGES — the new /incident-debug endpoint and 'incident-debug' tab are purely additive. metricsCollector frequency change (60s → 30s) doubles snapshot write rate but the table grows linearly and the existing prune logic handles it. Pre-v1.44.0 frontends ignore the new tab id and keep working.
  • CI — v1.44.0 is a minor release (.0 tag), macOS DMG rebuilds automatically. Builds run on the public-repo unmetered Actions allowance until the billing cycle resets next month — see v1.39.1 changelog for context.
v1.43.0 May 2026
  • MONITORING-WIDE INCIDENT RESILIENCE — v1.42.0 made the Query Insights tab survive incidents (multi-source dispatcher: profile → mongod log → cache). v1.43.0 extends the same treatment to the FOUR other tabs that suffer the same problem: Real Time, Members, Performance Advisor, Growth Tracker. Plus a new page-level Incident Mode banner that aggregates across all panels so operators see ONE clear signal: "3 of 5 monitoring panels are using a fallback source".
  • AGGRESSIVE TIMEOUTS — every monitoring endpoint had its mongosh timeout dropped from 30-90s to 5-30s based on what each endpoint actually needs to do: /realtime 60s → 5s (just db.serverStatus / currentOp); /member-metrics per-pod 45s → 5s; /performance 60s → 30s (heavier scan); /growth 90s → 30s (collStats over many collections). The point is to NOT make the operator wait 60-90s for a timeout when mongod is hung.
  • /REALTIME DISPATCHER — same multi-source pattern as v1.42.0's /query-insights, with chain: live serverStatus + currentOp via mongosh (5s) → cached snapshot (1s). No log-derived equivalent for live connection counts (logs don't carry that), so the chain is shorter than query-insights but still solves the "page goes blank" problem.
  • /MEMBER-METRICS PARTIAL DEGRADATION — because the route does Promise.allSettled across replica-set members, a single hung pod no longer blocks the whole replica view. Per-pod timeout dropped to 5s; if more than half the pods are unresponsive, the response is flagged with _incidentMode=true and a structured _fallbackReasons (e.g. "2 of 3 replica-set members are not responding within 5s"). On full failure the route serves the cached snapshot.
  • /PERFORMANCE TIGHTENED + STRUCTURED — live scan timeout reduced from 60s to 30s. The existing 30-min background collector + perfScans SQLite cache was already a fallback for fresh requests; v1.43.0 adds the structured _source / _staleSeconds / _incidentMode metadata so the UI can show the chip. _incidentMode triggers when cached scan is > 1 hour old (means at least one 30-min collection cycle was missed).
  • /GROWTH DISPATCHER — timeout 90s → 30s, cache fallback wired the same way as /realtime. Stale snapshot served with _staleSeconds + _incidentMode metadata when the live collStats fan-out fails.
  • PAGE-LEVEL BANNER — new IncidentModeBanner component aggregates the _incidentMode flag across all 4 monitoring data sources (realtimeData, queryInsights, perfData, growthData). Yellow chip at the top of the Monitoring page with: count of affected panels ("2 of 4 ..."), oldest staleness across all panels ("oldest data: 12m old"), collapsible per-panel breakdown showing which fallback is active per tab + which sources failed and why. Per-tab Incident Mode chip from v1.42.0 stays — page banner gives the at-a-glance signal, per-tab chip gives the detail.
  • IMPLEMENTATION CHOICE — didn't add new fallback sources for /member-metrics or /growth (no good log-derivable equivalent for replica-set state or per-collection storage stats). FTDC files are written by mongod regardless of query engine state but parsing requires implementing MongoDB's chunk format — deferred to a future release with a proper test corpus. The Prometheus mongodb_exporter scrape was considered but the exporter ALSO queries mongod for serverStatus, so during a real incident it's typically also stuck. Honest scoping: aggressive timeouts + cache fallback fixes 95% of the practical problem; the remaining 5% would need significant infrastructure work.
  • SHARED INCIDENT META TYPE — new IncidentMeta interface in types.ts mixed into RealtimeData / PerformanceData / GrowthData / QueryInsights via TypeScript intersection. Consistent shape across all the dispatcher-aware endpoints means the banner code doesn't need per-endpoint branches. Same _source / _generatedAt / _staleSeconds / _incidentMode / _fallbackReasons fields everywhere.
  • NUMBERS — backend tests: 1515 (unchanged — the route changes are wired through existing helpers; v1.42.0's 18 dispatcher tests + 16 log-parser tests cover the contract). Frontend tests: 416 → 430 (+14 IncidentModeBanner tests covering the pure aggregation helper computeBannerState + render branches: hidden/shown, age formatting, per-panel reasons, multi-panel aggregation, forceHide). Total: 1931 → 1945. Strict tsc -b green for both projects. Production build green. Zero new dependency CVEs.
  • NO BREAKING CHANGES — every endpoint adds the optional underscore-prefixed metadata fields. Pre-v1.43.0 frontend versions ignore them and continue to work (just without the page-level banner). The mongosh expressions and inline scripts are unchanged — timeouts tightened, response shape extended.
  • CI — v1.43.0 is a minor release (.0 tag), macOS DMG rebuilds automatically. Builds run on the public-repo unmetered Actions allowance until the billing cycle resets next month — see v1.39.1 changelog for context.
v1.42.0 May 2026
  • INCIDENT-RESILIENT QUERY INSIGHTS — the Mongo Monitoring → Query Insights tab no longer goes blank during incidents. Pre-v1.42.0 the page only knew how to read slow queries from system.profile via mongosh-over-kubectl-exec, which hangs when the database query engine is unresponsive. v1.42.0 adds a multi-source dispatcher that tries 3 independent data sources, fastest-wins.
  • THREE INDEPENDENT SOURCES (fastest wins, fail → next) — (1) live system.profile via mongosh, 5-second hard timeout (was 90s); (2) mongod's structured stdout log via kubectl logs, 10-second timeout — readable EVEN when the query engine is hung because kubelet captures stdout independently of the database process; (3) cached snapshot from the perf_scans table, always-on. The frontend gets the same response shape from any source plus _source / _staleSeconds / _incidentMode / _fallbackReasons metadata.
  • NEW PURE HELPER — services/monitoring/slowQueryFromLog.ts. Parses mongod 6.0+ structured JSON logs into the same query-insight shape system.profile produces. Extracts slow ops, aggregates by queryHash + ns + op, computes p50/p95/p99 percentiles, dedupes uniqueClients by IP, counts COLLSCAN occurrences, classifies command vs find vs aggregate. Skips system-namespace ops (admin.* / local.* / config.*). Empty / non-JSON / banner lines silently skipped. 16 unit tests cover every input shape we've seen in real mongod logs.
  • NEW PURE HELPER — services/monitoring/queryInsightDispatcher.ts. Pure dispatcher with per-source timeout race + structured fallbackReasons output. Caller passes 3 thunks; dispatcher returns the first success or throws with all per-source failure reasons concatenated. Includes withTimeout() utility (Promise.race with cancel timer) and buildAllSourcesFailedResponse() for HTTP-friendly 503 shape. 18 unit tests cover happy path, fallback chains (profile → log; profile → log → cache), all-sources-failed, incidentMode flag rules (only "profile + 0s stale" is non-incident), per-source timeout independence.
  • FRONTEND — new Incident Mode banner in MonitoringPage Query Insights tab. Renders a yellow chip when _incidentMode is true with: which source is serving (profile / log / cache), how stale the data is (in s/m/h depending on age), and a collapsible "Why each source failed" section showing per-source error reasons. Source pill in the header dynamically reflects the actual source instead of always saying "From Profiler". Plain English copy: "Live profiler unreachable — showing slow queries from mongod log" / "Both live profiler and log read failed — showing last cached snapshot".
  • WHY THIS MATTERS — during a real incident (replica-set election, lock storm, cache thrash, deadlock) mongod stays UP but the query engine can't serve queries against system.profile. Pre-v1.42.0 you'd see an empty Query Insights page — the worst possible time to lose visibility. v1.42.0 the page degrades gracefully through three sources before giving up, and tells you exactly what's working and what isn't.
  • IMPLEMENTATION CHOICE — cache only the LIVE profile result, not the log fallback. The log-derived data is approximate (no $indexStats, no profiler-specific fields) so caching it would degrade the next request's "fresh cache hit". Only the profile path can produce a future-friendly cache entry.
  • NUMBERS — backend tests: 1481 → 1515 (+34: 18 dispatcher tests + 16 log-parser tests). Frontend tests: 416 (unchanged — banner is a pure conditional render with no logic worth isolating; backend dispatcher tests cover the contract). Total: 1897 → 1931. Strict tsc -b green for both projects. Production build green. Zero new dependency CVEs.
  • NO BREAKING CHANGES — the /api/monitoring/<cluster>/query-insights endpoint shape is unchanged plus four optional underscore-prefixed metadata fields. Pre-v1.42.0 frontend versions ignore the new fields and continue to work (just without the banner). The dispatcher's "profile" path uses the EXACT same inline mongosh expression as before — same data shape on the happy path.
  • CI — v1.42.0 is a minor release (.0 tag), macOS DMG rebuilds automatically. Builds run on the public-repo unmetered Actions allowance until the org Actions billing cycle resets next month — see v1.39.1 changelog for context.
v1.41.2 May 2026
  • AUDIT LOG + ROLLBACK FOR DIRECT CONNECT + K8s-MANAGED — closes the implied promise from v1.40.0 (which said "SQLite persistence comes in v1.40.1") and v1.41.0. Pre-v1.41.2 the /api/browser-direct/ and /api/browser-k8s/ Safe Ops routes were writing audit IDs back to the UI but the entries themselves were ephemeral — the GET /audit-log endpoint returned [] as a placeholder. Now persisted to the same browser_audit_log SQLite table the PSMDB path has used since v1.34.x.
  • SCHEMA MIGRATION — browser_audit_log gets two new sibling columns: direct_connection_id (nullable) and managed_db_id (nullable). The legacy percona_cluster_id NOT NULL constraint stays for migrated DBs — non-PSMDB rows store empty string there to satisfy the constraint. Each route's GET /audit-log filters by its own ID column so no rows leak across the three target types. Same idempotent ALTER TABLE pattern used in v1.29 (managed_databases.direct_connection_id) and v1.34 (k8s_clusters discovery columns) — zero downtime, zero data loss on upgrade.
  • NEW SHARED HELPER — services/browser/auditLog.ts. Pure SQL builders (buildInsertStatement / buildListStatement / buildGetStatement / shapeRowToEntry) + thin wet wrappers that thread them through rawDb. Builders enforce a column-allow-list (pickColumn() rejects unknown targetType at runtime) so even a typo can't accidentally inject into the SQL string-interpolation slot. recordAuditEntry() / listAuditEntries() / getAuditEntry() are the public API used by all three browser routes.
  • ROLLBACK ENDPOINT — new POST /api/browser-direct/<id>/rollback/<auditId> + POST /api/browser-k8s/<id>/rollback/<auditId> matching the existing PSMDB /rollback. Auto-execution is wired ONLY for CREATEINDEX (→ dropIndex via runner.dropIndex with the captured index name). UPDATE / DELETE / INSERT can't be safely auto-undone without a pre-state snapshot we don't capture (would inflate Safe Ops latency to read affected docs before each write); for those ops the route returns the rollback script for manual review — user pastes into IntelliShell. Same auto-execution boundary the PSMDB /rollback has had since v1.34.
  • SECURITY — cross-target attack defence. getAuditEntry() filters by BOTH targetType + targetId, so a user can't guess an audit ID and trigger rollback under a different target. Whitelist-validated column name in pickColumn() prevents future maintainers from accidentally introducing SQL injection at the string-interpolation slot. All three routes inherit the existing openMongoAccess() orgId enforcement from v1.40.0 / v1.41.0 — cross-org rollback is impossible at the connection layer, this just adds another defence inside the route.
  • TESTS — 21 new pure-helper tests in services/browser/__tests__/auditLog.test.ts covering: column routing per targetType (PSMDB → percona_cluster_id, Direct Connect → direct_connection_id, K8s → managed_db_id; correct sentinel for non-PSMDB), unique audit ID per call, JSON serialisation of result (object → string, missing → "null"), pod + role defaults per target type, rollbackScript empty-string default, parameterised SQL (no string-interp values), per-target column selection in list / get queries, ORDER BY + LIMIT shape, unknown-targetType rejection, cross-target attack defence (mismatched targetId returns null), shapeRowToEntry public-field renaming, defensive JSON parse fallback, null column defaults.
  • DOC FIX — v1.40.0 changelog entry updated: "audit-log (in-memory for v1.40.0 — SQLite persistence comes in v1.40.1)" → "(SQLite persistence + matching /rollback/:auditId endpoint shipped in v1.41.2)". The original promise-of-v1.40.1 was misleading — v1.40.1 never shipped because v1.40.0 was the .0 minor and we went straight to v1.41.0. v1.41.1 was the security fix for the Console picker tenant leak. v1.41.2 is the actual delivery.
  • NUMBERS — backend tests: 1460 → 1481 (+21 auditLog pure-helper tests). Frontend tests: 416 (unchanged — no UI surface touched; existing audit-log + rollback UI in BrowserPage already worked, just got real backend data instead of []). Total: 1876 → 1897. Strict tsc -b green for both projects. Production build green.
  • NO BREAKING CHANGES — the response shape of /audit-log is identical to what PSMDB returns. Existing UI components consuming the endpoint just see real entries instead of empty arrays. The new ROLLBACK_DROPINDEX audit operation is purely additive (only emitted by the rollback path itself).
  • CI — v1.41.2 is a patch release (.2 tag), macOS DMG auto-skips per the v1.37 release.yml rules. Will manually trigger force_mac=true since this fix improves the audit trail across all platforms — same pattern as v1.39.1 / v1.39.2 / v1.41.1.
v1.41.1 May 2026
  • TENANT-ISOLATION FIX (security — info-disclosure) — the /query-playground/databases endpoint (the data feed for the Console picker) had a tenant filter that only checked the K8s parent's orgId. Direct Connect rows from other organisations leaked into the picker for non-super-admin users. The dispatch-time middleware (authorizeManagedDbAccess in routes/middleware/resourceAuth.ts) caught actual /execute attempts — so this was info-disclosure (other-org row names + dbTypes visible), not unauthorized execution. Still real, still worth a patch.
  • NEW HELPER — lib/orgScopeFilter.ts. Pure function `filterDatabasesByOrg(rows, opts)` checks BOTH parent records (k8sClusters AND directConnections) against the caller's orgId. Super-admin bypasses (sees everything). Legacy single-tenant installs with null orgIds work unchanged (null parent matches null user). Orphaned rows (neither parent record exists) are dropped — we can't verify ownership of something whose parent is missing. Reusable across other future endpoints that need the same treatment.
  • IMPACT — single-org / single-tenant deployments (which is everyone right now): zero practical impact, but the code is now correct so future multi-org SaaS rollouts get tenant isolation by default.
  • TESTS — 12 new pure-helper tests in src/lib/__tests__/orgScopeFilter.test.ts cover: super-admin bypass, K8s match / mismatch / missing parent, Direct Connect match / mismatch / missing parent (THE LEAK that v1.41.1 fixes), orphan rejection, legacy null-orgId installs (parent + user both null → match; user has org but parent is null → reject), Map.has() vs Map.get() distinction (so "parent missing" doesn't accidentally match "parent has null orgId"). Plus a realistic mixed-input test that mirrors the actual Console picker usage pattern.
  • AUDIT — swept the whole backend for `if (d.k8sClusterId)` patterns. Found 7 spots: this one was the actual security leak; 5 others are intentional product behaviour (rightsizing / DR testing / topology viz / backups are K8s-only by feature design); 1 (overview/databases.ts) was already correct (had separate Direct Connect branch). All 6 non-leak spots documented in the changelog so future maintainers know they were considered.
  • DEFENCE-IN-DEPTH — the v1.40.0 /api/browser-direct/ and v1.41.0 /api/browser-k8s/ route families both flow through openMongoAccess() which already enforces orgId match before opening any TCP socket / kubectl exec channel. The dispatch-time middleware authorizeManagedDbAccess covers /api/query-playground/execute. v1.41.1 adds the list-time filter so info-disclosure is also blocked.
  • NUMBERS — backend tests: 1448 → 1460 (+12: 12 pure-helper tests for orgScopeFilter). Frontend tests: 416 (unchanged — no UI surface touched). Total: 1864 → 1876. Strict tsc -b green for both projects. Production build green.
  • NO BREAKING CHANGES — the response shape of /query-playground/databases is unchanged. Single-tenant (no orgId) installs see no behavioural difference. Multi-org installs get correct tenant isolation — a behaviour upgrade, not a regression.
  • CI — v1.41.1 is a patch release (.1 tag), so per the v1.37 release.yml rules the macOS DMG build auto-skips. Linux + Windows binaries publish as usual; macOS DMG from v1.41.0 stays current via auto-update. Will manually trigger force_mac=true since v1.41.1 includes a security fix that all platforms should get — same pattern as v1.39.1 / v1.39.2.
v1.41.0 May 2026
  • FULL MONGO COVERAGE — v1.41.0 closes the last DB Studio gap. EVERY common MongoDB deployment topology (PSMDB / Atlas / self-managed mongod over TCP / SSH-tunneled / SOCKS5-proxied / Bitnami K8s / MongoDB Community Operator K8s / raw StatefulSet K8s) now gets the full Studio: database tree, IntelliShell tabs, Indexes module with $indexStats, Safe Ops with blast-radius gauge, document edit with diff confirmation, visual explain plan, NDJSON export. v1.40.0 closed the Direct Connect gap; v1.41.0 closes the K8s-non-Percona gap.
  • BACKEND — new /api/browser-k8s/<managedDbId>/... endpoint family parallel to /browser/<perconaClusterId>/... (PSMDB) and /browser-direct/<directConnectionId>/... (Direct Connect, v1.40.0). 14 endpoints mirroring the other two paths. All three families share the SAME services/browser/directRunner.ts module — the runner takes a MongoAccess interface (services/optimizer/mongoAccess.ts), and both TcpMongoAccess (driver) and KubectlExecMongoAccess (mongosh-over-exec) implement it identically. Zero new shaping logic.
  • OPERATOR-AWARE POD RESOLUTION — routes through openMongoAccess({managedDbId}) which uses services/k8sPodResolver.ts to find the right pod + container across operator conventions. Bitnami labels (`app.kubernetes.io/name=mongodb`), MongoDB Community Operator labels (`app=mongodb-svc`), raw StatefulSet pods, multi-container pods (operator sidecars), and stale bootstrap/backup pods all handled. Same resolver the Optimizer + Diagnose modules have used since v1.29.
  • FRONTEND — BrowserPage now accepts THREE prop variants: perconaClusterId (PSMDB), directConnectionId (Direct Connect), managedDbId (K8s-managed). The URL builder picks the right /api/browser{,-direct,-k8s}/<id> prefix automatically. New "K8s Managed / kubectl" badge replaces the env+cluster picker in K8s mode (analogous to v1.40.0's "Direct Connect / tcp" badge). Node-router toolbar hidden in both Studio modes (operator-managed / single-target deployments don't need replica-set role detection at the UI level).
  • ROUTING — MongoDBAdapter decision tree updated. Priority order: perconaClusterId → PSMDB Studio; directConnectionId AND no k8sClusterId → Direct Connect Studio; k8sClusterId AND dbType=mongodb → K8s-managed Studio; everything else → CommandAdapter (now a near-impossible state — every Mongo row should hit one of the three Studio branches). v1.40.0's "Direct Connect with ALSO k8sClusterId set → CommandAdapter" guard inverted: now K8s wins because it requires no extra network hop and the Studio still works fully via kubectl-exec.
  • GRACEFUL DEGRADATION — same as v1.40.0: $indexStats requires `clusterMonitor` privilege which not every K8s deployment grants. The runner catches the permission error and returns indexes WITHOUT usage badges. count() failure (e.g. on a view) falls back to batch length. Each panel degrades feature-by-feature instead of all-or-nothing.
  • SECURITY — every endpoint flows through openMongoAccess() which enforces orgId match (managed db's K8s cluster orgId === user.orgId, super_admin bypasses) before opening any kubectl exec channel. Shared lib/indexHelpers validators (SAFE_FIELD_RE, TTL only on single ascending field, partialFilterExpression must be a JSON object, _id_ cannot be dropped) run on ALL THREE paths — same rules, same error messages.
  • NUMBERS — backend tests: 1448 (no new pure-helper tests needed — directRunner is fully covered by the v1.40.0 suite which exercises both transports). Frontend tests: 411 → 416 (+5: 4 BrowserPage K8s mount tests verifying URL routing + picker hiding + node-router suppression + transport label, and 1 new Adapter routing test for the K8s priority inversion). Total: 1859 → 1864 (+5). Strict tsc -b green for both projects. Production build green. Zero new dependency CVEs.
  • NO BREAKING CHANGES — the existing /api/browser/ + /api/browser-direct/ route families are untouched. PSMDB + Direct Connect users see no behavioural change. The new /api/browser-k8s/ route family is purely additive. The MongoDBAdapter routing change for the (rare) "k8sClusterId AND directConnectionId both set" edge case favours the K8s path over Direct Connect — honest behaviour upgrade, not a regression (the Studio still works in both cases).
  • CI — v1.41.0 is a minor release (.0 tag), macOS DMG rebuilds automatically. Builds run on the public-repo unmetered Actions allowance until the org Actions billing cycle resets next month — see v1.39.1 changelog for the full context.
v1.40.0 May 2026
  • DB STUDIO FOR DIRECT CONNECT MONGO — v1.40.0 closes the last big capability gap for the Mongo Console: Direct Connect MongoDB targets (Atlas, self-managed mongod, SSH-tunneled, SOCKS5-proxied) now get the full DB Studio experience that was previously PSMDB-only. Database tree, IntelliShell tabs, Indexes module with $indexStats, Safe Ops with blast-radius gauge, document edit with diff confirmation, visual explain plan, NDJSON export — same UI, same shortcuts, same safety pipeline.
  • BACKEND — new /api/browser-direct/<directConnectionId>/... endpoint family parallel to the existing /api/browser/<perconaClusterId>/... PSMDB routes. Mounts in src/index.ts, dispatches via openMongoAccess({connectionId}) which already supports the official MongoDB driver via TcpMongoAccess (added v1.38.0 for the Console execute path). 14 endpoints: list databases, list collections, collection stats, find with totalCount, aggregate, explain (find), explain-aggregate, execute-mql with the same curated mongo-shell parser, index insights with $indexStats fallback, createIndex, dropIndex, validate (Safe Ops), safe-execute (Safe Ops), audit-log (in-memory for v1.40.0 — SQLite persistence + matching /rollback/:auditId endpoint shipped in v1.41.2).
  • NEW HELPER — services/browser/directRunner.ts. Pure functions that map BrowserPage operations to driver-native commands via runCommand({listDatabases:1}), runCommand({find:..., filter:..., limit:..., maxTimeMS:30_000}), runCommand({createIndexes:..., indexes:[...]}), and so on. Returns the SAME response shape the PSMDB path returns, so the frontend BrowserPage doesn't need per-mode branches — just URL prefix selection.
  • FRONTEND — BrowserPage now accepts directConnectionId alongside perconaClusterId. The URL builder (`apiBase`) flips from /browser/<id> to /browser-direct/<id> automatically. In Direct Connect mode the env+cluster picker is replaced by a static "Direct Connect · tcp" badge (one target by definition), the node-router toolbar is hidden (single-target, no replica-set role detection from driver level), and the /maintenance/clusters bootstrap fetch is skipped (saves a useless round-trip).
  • CHILD COMPONENTS — IndexManagerPanel + DocumentEditPanel both gained an `apiBase` prop (replaced the old `clusterId` prop) so they can target either /browser or /browser-direct based on what the parent passes down. Same pattern as v1.39.0's mqlIntrospect-driven `lastResultCollection` plumbing — the components stay mode-agnostic, the parent decides.
  • GRACEFUL DEGRADATION — $indexStats requires `clusterMonitor` privilege which Atlas Free tier and many shared deployments don't grant. The runner catches the permission error and returns indexes WITHOUT the usage badges instead of failing the entire panel. count() failure (e.g. on a view) falls back to batch length for totalCount. The whole page degrades feature-by-feature instead of all-or-nothing.
  • ROUTING — MongoDBAdapter routing decision tree (priority order): perconaClusterId set → PSMDB Studio; directConnectionId set AND no k8sClusterId → Direct Connect Studio; everything else → CommandAdapter. The "k8sClusterId set ALSO" guard handles the edge case where a row carries both — we route to CommandAdapter (the safer kubectl-exec path) rather than guessing intent.
  • SECURITY — every endpoint goes through openMongoAccess() which enforces orgId match (DirectConnection.orgId === user.orgId, super_admin bypasses) before opening any TCP socket. The shared lib/indexHelpers validators (SAFE_FIELD_RE, TTL only on single ascending field, partialFilterExpression must be a JSON object, _id_ cannot be dropped, etc.) run on BOTH paths — same rules, same error messages.
  • NUMBERS — backend tests: 1420 → 1448 (+28: directRunner pure helpers covering listDatabases / listCollections / collectionStats / find with safe-limit clamping / aggregate / explainFind / explainAggregate / indexInsights with graceful $indexStats fallback / createIndex with shared-validator integration / dropIndex with _id_ rejection / validateOperation blast-radius math / safeExecute update/delete/insert dispatch). Frontend tests: 402 → 411 (+9: 5 MongoDBAdapter routing tests covering all branches of the decision tree + 4 BrowserPage Direct Connect mount tests verifying URL routing, picker hiding, and node-router suppression). Total: 1822 → 1859 (+37). Strict tsc -b green for both projects. Production build green.
  • NO BREAKING CHANGES — the existing /api/browser/<perconaClusterId>/... route family stays exactly as it was; PSMDB users see no behavioural change. The IndexManagerPanel + DocumentEditPanel prop rename (clusterId → apiBase) is internal: BrowserPage is the only caller and was updated atomically. ConsoleDb gained an optional directConnectionId field (additive, backward-compatible).
  • CI — v1.40.0 is a minor release (.0 tag) and the macOS DMG rebuilds automatically. Builds run on the public-repo unmetered Actions allowance until the org Actions billing cycle resets next month — see v1.39.1 changelog for the full context.
v1.39.2 May 2026
  • MONGO CONSOLE AUDIT FIXES — four real issues caught during a full end-to-end audit of the Mongo Console after v1.39.1 shipped. One critical correctness bug, two minor correctness bugs, one UX gap. All four fixed in v1.39.2 with regression locks.
  • FIX 1 (CRITICAL CORRECTNESS) — document edit was saving to the WRONG collection when the user ran a query that targeted a different collection than the tab was opened on. Repro: open IntelliShell tab on `accountSettings` → type `db.users.find({})` and run → click pencil on a result row → the edit modal targeted `accountSettings` (the tab's open-time collection), not `users` (the actual query target). Fix: new `tab.lastResultCollection` field is set by `executeTabQuery` after parsing the MQL with the new `lib/mqlIntrospect.ts` helper. Edit modal + export filename + edit-row affordance all use `lastResultCollection || collection` now. Same bug pattern hit the export filename (saved as `db_accountSettings_export.json` even when the docs were from `users`).
  • FIX 2 (CORRECTNESS) — edit-doc modal silently failed to open when `selectedDb` was empty. Repro: Console picker mounts BrowserPage with a selected cluster but no left-tree selection → user types `use mydb` then `db.users.find()` → results render correctly → click pencil → nothing happens (the modal's gating clause `editingDoc && selectedCluster && selectedDb` short-circuited on the empty `selectedDb`). Fix: gate on `activeEditorTab?.database` instead — the active tab is always the source of truth, never the left-tree selection.
  • FIX 3 (UX) — single click on a collection now opens the IntelliShell tab. Pre-v1.39.2 it only "selected" the collection (set selectedColl for Safe Ops scope) and the user had to discover that double-click was needed to actually open an editor. Compass / Studio 3T users hit this immediately because their muscle memory is single-click → tab. New behaviour: single click opens (or focuses, if already open) a tab on that collection AND sets selected scope. Clicking the same collection again focuses the existing tab — no duplicates.
  • FIX 4 (CORRECTNESS) — the "Explain" button now correctly handles aggregate queries. Pre-v1.39.2 the frontend's explain handler unconditionally called the /explain endpoint (which is hardcoded to `find` on the backend), so `db.orders.aggregate([...])` got explained as `find({}).sort({}).explain()` — wrong query, wrong plan. Also the regex extracting the query body was greedy and captured chained method calls (`.limit(10).sort({...})`) into the body. Fix: new backend `POST /browser/<cluster>/explain-aggregate` endpoint runs `db.coll.explain("executionStats").aggregate(pipeline)` and returns the same shape as /explain (so the visual ExplainPlanView renders both identically). New `detectExplainableOp` helper uses balanced-bracket parsing so chained methods stay out of the body.
  • NEW HELPER — `frontend/src/pages/operations/Browser/lib/mqlIntrospect.ts` (pure module). Two best-effort functions: `extractCollectionFromMql(mql)` returns the collection name from `db.<coll>.<method>(...)` or `db.getCollection("<coll>").<method>(...)`, undefined for unsupported shapes (`show dbs`, `db.runCommand({...})`, etc.). `detectExplainableOp(mql)` returns `{op, collection, body}` for find/aggregate, undefined otherwise — used by the Explain button dispatch. 17 unit tests cover every shape we've seen: dot syntax, getCollection() syntax, chained methods, system.profile dotted collection names, empty input, comments-only input, multi-statement scripts, trailing semicolons.
  • TEST COVERAGE — 4 new BrowserPage interaction tests in browserPageTree.test.tsx: single click on collection opens a tab, second click on same collection focuses existing tab (no duplicate). 17 new mqlIntrospect helper tests (every input shape). 2 new explainParser tests for aggregate-shape explain output. Frontend: 383 → 402 (+19). Backend: 1419 → 1420 (+1). Total: 1802 → 1822.
  • NO BREAKING CHANGES — EditorTab gained an optional `lastResultCollection` field (never read by external code). New backend endpoint /explain-aggregate is purely additive. Single-click behaviour is strictly more useful than before — anyone who relied on "click selects without opening" can use the dropdown picker inside Safe Ops / Indexes modules instead.
  • CI — v1.39.2 is a patch release (.1+ tag), so per the v1.37 release.yml rules the macOS DMG build auto-skips. We will manually trigger force_mac=true for this release because v1.39.2 is a Mac-affecting fix (Mac users on v1.39.0 still have the saving-to-wrong-collection bug). v1.39.1 already shipped a forced Mac build for the editor-loading fix — same pattern here.
v1.39.1 May 2026
  • EDITOR FIX — Mongo Console editor stuck at "Loading editor…" is fixed. Symptom: opening any IntelliShell tab on a collection (single click in left tree → tab opens → editor shows the Monaco loading message forever, no syntax highlighting, no completion). Same symptom for the SQL Console + every other adapter that mounts MonacoSqlEditor. Reproducible offline, in Electron, behind corporate proxies, on slow networks — anywhere outbound HTTPS to jsdelivr is blocked or slow.
  • ROOT CAUSE — @monaco-editor/react defaults to fetching the entire monaco-editor package from a CDN (jsdelivr) at runtime instead of using the bundled npm package. There was no loader.config({ monaco }) call anywhere in the app, so every editor mount triggered the CDN load path. Inside the Electron app shipped to users this means: the desktop binary is 168 MB but still needs to phone home to jsdelivr to render an editor. CSP and proxy environments block it; no error surface, just an infinite spinner.
  • FIX — new src/setup/monacoSetup.ts module loaded once at app entry (BEFORE any component imports the editor). Calls loader.config({ monaco }) so @monaco-editor/react resolves immediately from the bundled monaco-editor package. Wires self.MonacoEnvironment.getWorker to Vite-bundled workers (editor.worker, json.worker, css.worker, html.worker, ts.worker — all imported with Vite's ?worker suffix so they emit as standalone bundles). Calls loader.init() eagerly so the first editor mount is instant. Net result: zero network calls for the editor, ever.
  • BUNDLE IMPACT — +5 worker bundles in dist/assets (editor.worker 30 KB, json.worker 23 KB, css.worker 165 KB, html.worker 92 KB, ts.worker 1.2 MB). The big monaco-editor chunk (3.6 MB / 926 KB gzip) was already lazy-loaded on first editor mount; same chunk size, but now it lives in the app bundle instead of jsdelivr. Total app size up by ~1.5 MB; offline-first reliability up by infinity.
  • REGRESSION LOCK — new src/setup/__tests__/monacoSetup.test.ts (7 tests) verifies: main.tsx imports monacoSetup BEFORE App; monacoSetup imports the bundled monaco-editor; loader.config({ monaco }) is called; all 5 worker imports use the Vite ?worker suffix; MonacoEnvironment.getWorker handles every label Monaco asks for; loader.init() is called for eager bootstrap. Catches the "someone removed the loader.config and shipped a hung-editor build" class of regression at PR review time, not after release.
  • NUMBERS — frontend tests: 376 → 383 (+7). Backend tests: 1419 (unchanged — frontend-only fix). Total: 1795 → 1802. Strict tsc -b green. Production build green (5 worker bundles emitted as expected).
  • NO BREAKING CHANGES — pure additive bootstrap module + one import in main.tsx. Every existing editor (SafeEditor in SQL/Mongo/Redis/etc. Console adapters, IntelliShell in BrowserPage, query editor in Optimizer) picks up the bundled loader automatically.
  • CI — v1.39.1 is a patch release (.1 tag), so per the v1.37 release.yml rules the macOS DMG build auto-skips. Linux + Windows binaries publish as usual; macOS DMG from v1.39.0 stays current via auto-update. Estimated minutes saved: ≈30 vs a full-platform build.
v1.39.0 May 2026
  • MONGO CONSOLE — DAILY-DRIVER PARITY — v1.39.0 closes the last five functional gaps between DBHelm Console and Compass / Studio 3T / NoSQL Booster for the operations a typical Mongo developer does every day. Five new features, 181 new tests, zero breaking changes.
  • NEW — visual explain plan. Click "Explain" next to Run on any db.<coll>.find(...) or .aggregate(...) and a Compass-style stage tree opens in a side drawer: depth-indented IXSCAN/FETCH/SORT/LIMIT/PROJECTION_* boxes with per-stage docs/keys examined, nReturned, executionTimeMillisEstimate, and the index name they used. Slow stages (>50ms) flagged in red. Summary chips at the top: scan type (IXSCAN+FETCH / COLLSCAN / IXSCAN / MIXED / UNKNOWN), covered-query badge, total docs vs returned, indexes used. Heuristic warnings: "Full collection scan", "Examined N docs to return M (X× over-fetch)", "In-memory sort detected", "Slow query > 1s". Rejected plans collapsed by default, expandable in one click. Raw JSON toggle for the deep-dive case. Pure helper (services/browser/explainParser.ts) covered by 12 backend + 6 frontend tests across MongoDB 5.x and 6.x explain payloads.
  • NEW — index management UI. New "Indexes" module tab next to Explorer / Safe Ops. Lists every index on the selected collection with badges (default _id_ → lock icon, unique → purple, sparse → grey, TTL → amber + seconds), the index key in mono, and $indexStats usage (ops since date) when available. "New Index" form: compound up to 32 fields, direction picker (1 / -1 / text / 2dsphere / 2d / hashed), name (auto-suggested as field_dir_field_dir), unique / sparse / background flags, advanced section for TTL seconds (validated single-field-only), partial filter expression (parsed as JSON), and collation (parsed as JSON). All validation runs client-side in lib/indexHelpers.ts BEFORE the POST so users see field errors instantly. Backend mirror in services/browser/indexHelpers.ts re-validates so a tampered request can't slip through. Drop is two-click: red trash → "Confirm Drop" appears → second click fires DELETE. The default _id_ index never shows a drop button (Mongo rejects it server-side too). Audit-logged with rollback script.
  • NEW — document edit panel with diff confirmation. Hover a row in Tree or Table view → small pencil icon appears → click opens a guided JSON edit modal. Paste from anywhere, edit in place, the parser shows inline errors as you type ("Invalid JSON: Unexpected token", "Document must be a JSON object"). Click "Preview Changes" → a per-field diff appears: ADDED in green, REMOVED in red strikethrough, CHANGED with old → new arrow, UNCHANGED hidden by default. Save builds {$set, $unset} from the diff (skipping _id which Mongo rejects), POSTs through Safe Ops /safe-execute (which already has destructive-op gating + audit + rollback script). The diff confirmation is the safety belt none of the other IDEs ship by default — every Mongo edit is irreversible, this means you see exactly what's about to change.
  • NEW — NDJSON export + helper-driven serializer. Export menu in the result toolbar now has three formats: JSON (pretty-printed array), CSV (RFC-4180 with the right quoting for embedded commas, double-quotes, newlines, and leading/trailing whitespace), NDJSON (one JSON document per line — streamable, pipes into mongoimport / jq cleanly). Mongo Extended-JSON shorthand for ObjectId ({$oid}) and Date ({$date}) renders as the inner string in CSV cells (so spreadsheets show 507f1f77... not the wrapper object). Pure helper (services/browser/exportHelpers.ts + frontend mirror) covered by 28 backend + 12 frontend tests across every CSV escape edge case we could think of.
  • NEW — row-level edit affordance in Table View. Hover a row → the # column shows a small edit icon → click loads the document into the new edit panel. Same icon in Tree View, top-right of each row, only when _id is present (we can't safely update without it).
  • BACKEND — two new endpoints on browser.ts: POST /:cluster/databases/:db/collections/:coll/indexes (createIndex with shape validation via buildCreateIndexExpr), DELETE /:cluster/databases/:db/collections/:coll/indexes/:name (dropIndex with default-_id_ rejection via buildDropIndexExpr). Always routed to PRIMARY (write op). Audit-logged with rollback script (drop ↔ create are inverses). Same JSON-only-data discipline as the rest of the module — no user string ever flows into the shell unescaped.
  • CONSOLE CORNER-CASE TEST PASS — 41 new corner tests in consoleCorners.test.tsx covering: destructive-op 409 → confirm modal flow on every adapter, 403 readOnlyBlocked surfacing as a toast (not a crash), 429 rate-limit surfacing as a toast, empty-query no-op (Execute disabled / no POST), schema-tree filter never re-expands collapsed schemas (v1.38.0 regression lock), MongoDBAdapter routing decision (Percona PSMDB → BrowserPage; Direct Connect → CommandAdapter), Direct Connect Postgres / MySQL / MongoDB / MariaDB / ClickHouse all render without the v1.37.1 banner, every adapter renders for both K8s-discovered AND Direct Connect modes (no banner, no crash), Monaco wrapper mounts with javascript for mongo and sql for postgres.
  • NUMBERS — frontend tests: 267 → 376 (+109). New helper tests: exportHelpers (12), docDiff (15), explainParser (6), indexHelpers (14). New component mount tests: ExplainPlanView (5), IndexManagerPanel (8), DocumentEditPanel (8). New Console corner-case suite: consoleCorners (41). Backend tests: 1347 → 1419 (+72). New helper tests: indexHelpers (32), explainParser (12), exportHelpers (28). Total: 1614 → 1795 unit + smoke checks.
  • NO BREAKING CHANGES — BrowserPage props, ConsolePage adapter map, and the /browser API surface are all preserved. The new endpoints (POST + DELETE /indexes) are purely additive — every existing client continues to work. The Indexes module tab is a new addition to the existing Explorer / Safe Ops set; no existing tab moved or renamed.
  • CI — v1.39.0 is a minor release (.0 tag), so per the v1.37 release.yml rules the macOS DMG rebuilds. Saves the patch-release skip optimisation for the next v1.39.x.
v1.38.1 May 2026
  • MONGO INTELLISHELL — the IntelliShell editor in the MongoDB Studio (BrowserPage) is now Monaco. Same engine VS Code, GitHub.dev, and our SQL Console use. Real JavaScript syntax highlighting (mongosh is JS-shaped, so brackets, strings, comments, and regex literals all colour correctly), bracket matching, multi-cursor (Cmd+D), smart indent, find / replace (Cmd+F / Cmd+Option+F), code folding, line wrapping, real line numbers — all of it. Replaces the hand-rolled <textarea> + manual line-number gutter that had been the editor since v1.20.
  • MONGO COMPLETION — Monaco's completion provider is now wired to the live database tree. Type "db." → every collection in the currently-scoped database appears (sourced from collectionsByDb cache, so no extra network call). Type "db.<coll>." → find/findOne/aggregate/distinct/getIndexes/stats/explain snippets. Type "$" inside an aggregate() array → every pipeline operator ($match, $group, $project, $sort, $limit, $unwind, $lookup, etc.) with insert templates. Triggers on `.`, ` `, and `$`. Same Compass / Studio 3T / NoSQL Booster muscle memory — same kbd shortcuts (↑/↓/Tab/Esc).
  • TREE FIX — chevron really collapses now. Old behaviour: clicking a database in the IntelliShell tree only ever called setSelectedDb — there was no toggle, so the same db stayed expanded forever and clicking elsewhere collapsed it as a side-effect of selection moving. New behaviour: chevron is its own click target with aria-expanded; clicking it flips a dedicated expandedDbs Set (no relation to selectedDb). Same fix-pattern we shipped for SQLAdapter in v1.38.0 — collapse state lives in a Set completely separate from data, so re-renders, refreshes, filter typing, and tree fetches can't accidentally re-expand what the user just closed.
  • COMPASS BEHAVIOUR — multiple databases can be expanded at the same time. Old code tied the entire children block to `selectedDb === d.name`, so opening a second database collapsed the first. Now any number of dbs can be open simultaneously, just like Compass / Studio 3T. Each db row also shows its loaded collection count (small monospace badge on the right) so you can see at a glance which dbs you've poked into.
  • PER-DB COLLECTION CACHE — collapse + re-expand is instant. Collections fetched from /browser/<cluster>/databases/<db>/collections are now stored in a Record<dbName, CollInfo[]> cache. Collapsing a db keeps the cache; re-expanding it pulls from cache (no network round-trip) until the user explicitly refreshes the tree. Tested via collCalls counter — second expansion of the same db does NOT add a fetch.
  • EDITOR-SPECIFIC AFFORDANCES — the new <MonacoSqlEditor fill /> mode lets a parent flex container drive height (the IntelliShell editor uses height: 100% to fill its split-pane half exactly). Per-tab undo history preserved via path={`browser-${tab.id}`}. Cmd+Enter still runs the query, with the suggest widget no longer swallowing the keystroke (Monaco's addCommand API beats textarea onKeyDown).
  • NUMBERS — frontend tests: 264 → 267 (+3). New BrowserPage tree tests cover: chevron toggle truly collapses (not just selects), multiple dbs stay open simultaneously, per-db cache survives collapse/re-expand. Backend tests: 1347 (unchanged). Total: 1614 unit + smoke checks.
  • NO BREAKING CHANGES — the BrowserPage props, /browser API surface, and editor tab shape are unchanged. The hand-rolled autocomplete dictionary is gone (Monaco supersedes it for every match pattern it covered) but no public surface depended on it.
  • CI — v1.38.1 is a patch release (.1 tag), so per the v1.37 release.yml rules the macOS DMG build auto-skips. Linux + Windows binaries publish as usual; macOS DMG from v1.38.0 stays current via auto-update. Estimated minutes saved: ≈30 vs a full-platform build.
v1.38.0 May 2026
  • DIRECT CONNECT CONSOLE — the v1.37.1 banner is gone. Console now drives Direct Connect Postgres, MySQL, and MongoDB targets through the official drivers (the same TcpPgAccess / TcpMysqlAccess / TcpMongoAccess abstractions Optimize + Diagnose have used since v1.29–v1.31). RDS, Cloud SQL, Azure DB, self-managed nodes over plain TCP, anything behind an SSH tunnel, and any target reachable through a SOCKS5 proxy: all work end-to-end with the same UI as the Kubernetes-discovered path.
  • NEW — unified dispatcher in /api/query-playground/execute. Detect order: SaaS (BigQuery / Snowflake / Redshift / Databricks) → SaaS path; directConnectionId → Direct Connect path; k8sClusterId → kubectl exec path. Same destructive-op detection, read-only gating, EXPLAIN wrapping, and audit logging on every path. Same response shape, so the frontend doesn't need to fork. Same applies to /export.
  • NEW — Direct Connect Postgres SQL execution path: opens TcpPgAccess (which already plumbs SSH tunnel via openConnectionTunnel + SOCKS via socksConnect), enforces LIMIT injection on bare SELECTs, wraps in BEGIN READ ONLY; ... ROLLBACK; when read-only mode is on (so even an accidental write is rolled back), wraps in EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON) when explain mode is on. Returns the same {rows, columns, durationMs, target} shape as the K8s path so the SQL IDE just works.
  • NEW — Direct Connect MySQL execution path: opens TcpMysqlAccess (driver: mysql2 with SSH/SOCKS support), runs SET SESSION TRANSACTION READ ONLY when read-only is on, plain EXPLAIN for explain mode, default 100-row cap on bare SELECTs. SHOW DATABASES / SHOW TABLES / SHOW COLUMNS introspection works the same as the K8s path.
  • NEW — Direct Connect MongoDB execution path: opens TcpMongoAccess (official driver, native SOCKS5 + SSH-tunnel via mongodb URL rewriting). Because the driver doesn't evaluate JavaScript like mongosh does, we ship a small curated mongo-shell parser (mongoShellParser.ts) that translates the patterns users actually type into runCommand documents: show dbs/databases/collections/users/roles/profile/log, use <db>, db.runCommand({...}), db.adminCommand({...}), db.<coll>.find/findOne/countDocuments/estimatedDocumentCount/aggregate/distinct/getIndexes/stats with chained .limit(N) / .sort({...}) / .skip(N) / .projection({...}) / .toArray(). Loose JSON is supported (single quotes, unquoted keys) so copy-paste from mongosh history Just Works. Anything we don't recognize throws a clear, actionable "Direct Connect Mongo Console supports: ..." error instead of a silent failure.
  • FIX — schema-tree collapse is now sticky. Clicking a schema chevron to collapse it used to bring it back open after typing in the filter or any unrelated re-render, because open/closed lived inside the tree data structure that other code paths spread {...s, open: true} over. Now open/closed lives in two dedicated Sets (openSchemas / openTables) completely separate from the tree data — filter typing, refreshes, completion-schema rebuilds: nothing can mutate it except the toggle handlers themselves. New interaction tests (sqlAdapterOpenState.test.tsx) lock the behaviour in: collapse → type filter → still collapsed; collapse → type a filter that matches a child table → still collapsed (no force-expand).
  • FIX — better Postgres "no schemas visible" empty state. The old text was "No schemas visible — user may lack SELECT on catalog." For users connected to the postgres system database (which has zero user schemas by default) this was technically wrong and misleading. New copy is engine-aware: Postgres explains the system-DB-vs-app-DB distinction; MySQL mentions SHOW DATABASES privilege; everything else falls back to the generic message. Plus a Refresh action button right inside the empty state.
  • NUMBERS — backend tests: 1282 → 1347 (+65). New mongoShellParser.test.ts covers 42 cases across shell helpers, db.runCommand JSON parsing, find with chained limit/sort/skip/projection, aggregate pipeline parsing, distinct/count/getIndexes/stats, and every error branch users will actually hit. New directConnectExec.test.ts covers 23 cases for engine detection (Postgres / MySQL / Mongo families + unsupported), enforceSelectLimitForDirectConnect (LIMIT injection, FETCH FIRST/NEXT respect, non-SELECT pass-through), buildEffectiveSql (read-only wrapping, explain wrapping, the explain-wins-over-read-only override), and validateDirectConnectDbName (allowed chars + shell-metacharacter rejection). Frontend tests: 259 → 264 (+5). 3 new adapter mount tests verify the v1.37.1 banner is gone for Direct Connect Postgres / MySQL / MongoDB. 2 new SQLAdapter interaction tests lock the collapse behaviour. Total: 1611 unit + smoke checks.
  • NO BREAKING CHANGES — the K8s and SaaS paths are untouched (same code, same response shape). Existing Direct Connect targets that already worked in Optimize + Diagnose now also work in Console, no migration needed. The /query-playground/execute error message for unsupported targets has changed from "Query Playground requires Kubernetes-managed databases" to "Query Playground requires Kubernetes-managed or Direct Connect databases" — if anything was string-matching that error, update it.
  • CI — v1.38.0 is a minor release (.0 tag), so per the v1.37 release.yml rules the macOS DMG rebuilds. Saves the patch-release skip optimisation for the next v1.38.x.
v1.37.1 May 2026
  • CONSOLE UX FIXES — three small but visible bugs the v1.37.0 surface exposed once users started clicking through real PSMDB clusters in the picker.
  • FIX — MongoDB Studio auto-selects the cluster you picked. Clicking a PSMDB card in the Console picker now opens the DB Studio with Environment + Cluster pre-filled to the cluster you JUST chose. Previously the dropdowns were empty placeholders, forcing you to re-select the same cluster a second time. MongoDBAdapter now passes db.perconaClusterId to BrowserPage as a prop; BrowserPage gives the prop priority over the legacy ?cluster=<id> URL param.
  • FIX — DB Studio editor no longer stretches to the height of the database tree. When you expanded a database with 50+ collections, the right-side IntelliShell editor was growing vertically to match the tree, dragging the entire layout off-screen. Root cause: BrowserPage uses h-full and MongoDBAdapter wrapped it in a div with no height constraint. Fix: the wrapper now uses h-[calc(100vh-240px)] with a 600px min-height — the database tree scrolls independently inside this container, the editor stays at a stable, predictable size.
  • FIX (HONEST) — Direct Connect Console now shows a clear "coming in v1.38.0" banner instead of a confusing 400 error after you type and run a query. The /query-playground/execute route currently rejects any database without a k8sClusterId (line 687 of queryPlayground.ts). v1.38.0 wires up TcpPgAccess / TcpMysqlAccess / TcpMongoAccess (the same abstractions Optimize + Diagnose use since v1.29-v1.31) so Direct Connect targets get Console too. Until then, the banner is up-front about the gap and points to Optimize + Diagnose which DO already work for Direct Connect.
  • NUMBERS — frontend tests: 259 (unchanged), backend tests: 1282 (unchanged), strict typecheck green. Pure UI fixes; zero new tests because no new pure logic was added.
  • NO BREAKING CHANGES — BrowserPage perconaClusterId prop is optional with the URL param fallback preserved.
  • CI — first patch release that auto-skips the macOS build per the v1.37 release.yml rules. Saves ~30 billed minutes vs the old behavior. Linux + Windows binaries published as usual; macOS DMG from v1.37.0 stays current via auto-update.
v1.37.0 May 2026
  • CONSOLE BECOMES A REAL IDE — the four big additions on top of the v1.36 polish: Monaco editor with engine-aware completion, multi-tab editor, result-row inspector, and live mini-charts on the workspace landing page. Together these close the last functional gap with Studio 3T / DataGrip / pgAdmin / MongoDB Compass for the daily-driver flow on Postgres / MySQL / MongoDB.
  • NEW — Monaco editor swap. Replaces the textarea in SafeEditor with @monaco-editor/react@4 + monaco-editor@0.55 (with a pinned dompurify >=3.3.4 override to clear all 8 transitive CVEs). Engine detection auto-picks the language: sql for postgres/mysql/mssql/snowflake/redshift/bigquery/spark/clickhouse/cassandra; javascript for mongo (mongosh is JS-shaped, so bracket matching + comment toggling work); plaintext for redis/kafka/elastic/generic. Per-editor completion provider (no global Monaco state) so multiple Console pages don't leak suggestions across each other.
  • NEW — engine-aware completion suggestions. Postgres: 27 common SQL keywords + Postgres-specific extras (LATERAL, RETURNING, pg_size_pretty, OVER, NULLS FIRST/LAST). MySQL: SHOW DATABASES, SHOW PROCESSLIST, STRAIGHT_JOIN, USE INDEX. Mongo: db / find / aggregate / 26 $-prefixed operators ($match, $group, $lookup, $unwind, $eq, $gte, $exists, $regex, $set, $inc, etc.). Plus suggestions sourced from the schema tree the SQLAdapter already loads — schema names, qualified+bare table names, column names with type hints, and "select-{table}" snippets that insert SELECT * FROM schema.table LIMIT 100. Trigger characters: . space $.
  • NEW — Monaco-native keybindings. ⌘/Ctrl + Enter (run), ⌘/Ctrl + E (explain), ⌘/Ctrl + Shift + F (format) registered via editor.addCommand so the suggestion widget no longer swallows them. Refs+state ensure the keybindings always invoke the freshest handler instead of a stale closure.
  • NEW — multi-tab editor (up to 8 tabs per database). Each tab has its own query text + optional target database + display title, persisted to localStorage so reloading Console keeps in-progress queries. Tab strip features: + button to add, X to close (the last tab CAN'T be closed — it just clears), double-click title to rename (60-char cap, whitespace-only is a no-op), drag-and-drop to reorder, dot indicator when a tab has unsaved query content. New tabs default to empty. The active tab's query is what runs / formats / exports / records to history. Result rows clear on tab switch (each tab has its own result mental model; we don't balloon memory with N stored result sets).
  • NEW — result row inspector. Click any row in the table view → right-side slide-in panel shows every column with a per-column type tag (string / number / boolean / date / json / null) + Copy button per column + "Copy as JSON" for the whole row. Type inference: numbers, booleans, ISO timestamps (regex match), nested objects/arrays as pretty JSON, NULL distinctly rendered. Esc closes; backdrop click closes; X closes. Z-layered below the destructive-confirm modal so the modal still wins.
  • NEW — workspace landing live mini-charts. The /db/:id overview page now shows 3 sparklines that poll /api/database/:managedDbId/realtime every 5s for the supported engine families: connections, ops/sec, cache-hit %. Engine-aware extraction: Postgres derives transactions/sec from xact_commit + xact_rollback deltas; MySQL derives queries/sec from SHOW GLOBAL STATUS counter delta; Mongo sums opcounters delta + computes WiredTiger cache-used %; Redis reads opsPerSec + hitRate directly. Rolling 30-sample window. Sparklines are raw SVG (no recharts pull on the landing route — keeps the workspace bundle small). Fall-through "no live extraction yet" card for unsupported engines (Kafka, Elastic, warehouses).
  • POLISH — result table renders NULL distinctly (italic muted "NULL") instead of empty cell. Clicking a row highlights it (primary-tint background) so users know which row is being inspected.
  • COMPATIBILITY — SafeEditor consumers (all 13 Console adapters) work unchanged. The new completionSchema prop is fully optional. SQLAdapter opts in by mapping its tree state to a CompletionSchema via useMemo — zero new API calls, the schema is the same data the adapter already shows in the left panel.
  • SECURITY — added npm override "dompurify": ">=3.3.4" to clear the 8 moderate CVEs that monaco-editor@0.55 pulls transitively (XSS, prototype pollution, SAFE_FOR_TEMPLATES bypass, FORBID_TAGS bypass, mutation-XSS via re-contextualization). npm audit reports 0 vulnerabilities post-override.
  • NUMBERS — frontend tests: 191 → 259 (+68, all green). 24 cases for monacoCompletion (engine detection, language map, schema-driven items, snippet generation), 16 cases for useEditorTabs (lifecycle, persistence, reorder, malformed-storage tolerance, last-tab-clear semantics), 14 cases for workspaceLiveMetrics (per-engine extraction, derivative calc, null-handling, clock-skew protection, formatter), 11 cases for RowInspector (mount, type inference, Esc/backdrop/X close, NULL rendering, JSON pretty-print). Backend tests: 1282 (unchanged). Total: 1541 unit + smoke checks per CI run. Strict frontend typecheck (tsconfig.app.json) + backend typecheck both green.
  • NO BREAKING CHANGES — zero backend route changes, zero schema changes, zero adapter API changes. The SafeEditorHandle imperative API was already unused (no adapter called .focus() / .setQuery() via ref) and is preserved on the type for forward compatibility.
v1.36.0 May 2026
  • CONSOLE POLISH FOR THE BIG 3 (Postgres / MySQL / MongoDB) — the two surfaces we lead with for free-tier marketing get the table-stakes IDE features they were missing. No backend changes; pure frontend polish anyone with a free DBHelm can use immediately.
  • NEW — query history panel. Every Console execute is auto-recorded to localStorage (per-database key, last 50 entries, FIFO eviction). The History dropdown in the editor toolbar shows query preview + relative time ("5m ago") + the target database used. Click any entry to recall it into the editor. Clear button wipes per-database history. Skips immediate duplicates so re-running the same query 10 times in a row stays one entry. Skips blobs >5000 chars to keep localStorage healthy. Pure frontend — zero new API surface, zero new audit-log noise.
  • NEW — SQL formatter button. Wired sql-formatter@15 into SafeEditor. Auto-detects the right dialect for the current adapter: postgresql for cnpg/percona-pg/timescale/yugabyte/citus/cockroach/patroni; mysql for mysql/mariadb/pxc/galera/percona-server-mysql; tsql for mssql; snowflake / redshift / bigquery / spark for the warehouses; generic sql for clickhouse/cassandra. Format button is hidden (not just disabled) for non-SQL engines (Mongo / Redis / Kafka / Elastic / Vector DBs / Neo4j / Influx) so the UI never offers an action that would mangle the syntax. Keyboard shortcut: ⌘+Shift+F.
  • NEW — keyboard-shortcut hint badges in the editor footer. ⌘+Enter run · ⌘+E explain · ⌘+Shift+F format. macOS shows ⌘, Windows/Linux shows Ctrl (auto-detected from navigator.platform). Improves discoverability for users who never read a docs page — they see the bindings inline.
  • POLISH — Monitoring empty states for the big 3 are now engine-aware and actionable instead of generic. Postgres: "DBHelm scrapes pg_stat_database, pg_stat_activity and pg_stat_replication every refresh interval. Make sure the connection user has SELECT on pg_catalog views (default for any Postgres role)." MySQL: "DBHelm reads from SHOW GLOBAL STATUS, SHOW PROCESSLIST and information_schema. Make sure the user has the PROCESS privilege so InnoDB stats and the process list are visible." MongoDB: "DBHelm collects from db.serverStatus(), db.currentOp() and rs.status(). Make sure the user has the clusterMonitor role for full visibility." Plus query-insight specific hints (pg_stat_statements / performance_schema / system.profile setup commands).
  • POLISH — "Real-time view not available" panels now name the engines that ARE supported (Postgres, MySQL, MongoDB, Redis, Kafka, Elasticsearch, ClickHouse, Cassandra, RabbitMQ, InfluxDB) so users can route to the right adapter. "Waiting for the first sample" panels include a Refresh-now button and explain that data usually arrives within 10 seconds.
  • COMPATIBILITY — keep all existing SafeEditor consumers working unchanged. The history-record + format additions live entirely inside SafeEditor; adapters (SQLAdapter, MongoDBAdapter, all 13 engine adapters) need zero changes. The optional onBeforeExecute parent hook is preserved for adapter-specific side effects.
  • NUMBERS — frontend tests: 167 → 191 (+24, all green). Backend tests: 1282 (unchanged). Total: 1473 unit + smoke checks per CI run. New tests: 12 cases for useQueryHistory (recall, dedupe, FIFO cap, per-DB isolation, persistence, malformed-storage tolerance), 12 cases for sqlFormatterDialect (every engine routed correctly, case-insensitive, fallback semantics).
  • NO BREAKING CHANGES — zero backend route changes, zero schema changes, zero adapter API changes. Existing query-execute flow / read-only gate / destructive-op confirmation modal / export menu all preserved exactly. Pure additive UX layer.
v1.35.0 May 2026
  • CONSOLE HARDENING — closes every gap from the v1.34.5 audit. Server-side destructive-ops detection now covers 6 more engines: Kafka / Strimzi (kafka-* CLI tools), Memcached (text protocol), RabbitMQ (rabbitmqctl + rabbitmqadmin), etcd (etcdctl), MinIO (mc CLI). Per-adapter mount + safety-wiring tests verify all 13 adapters import the canonical SafeEditor primitive (or, for MongoDB, route through the bespoke Studio + CommandAdapter fallback that both wire safety).
  • NEW — Kafka destructive-ops detection. Patterns: kafka-topics --delete (destructive), --alter (mutating), --create (mutating); kafka-acls --add/--remove (destructive — credential surface change has same blast radius either way); kafka-configs --delete-config (destructive); kafka-consumer-groups --delete + --reset-offsets (destructive); kafka-leader-election + kafka-reassign-partitions --execute (mutating); kafka-console-producer + kcat -P (mutating writes). Read-only ops like --describe / --list pass through clean. Also matches strimzi dbType.
  • NEW — Memcached destructive-ops detection. flush_all (destructive), delete <key> (destructive), set/add/replace/append/prepend/cas (mutating), incr/decr (mutating). get/stats/version pass through.
  • NEW — RabbitMQ destructive-ops detection. delete_user / delete_vhost / delete_queue / delete_exchange / delete_binding / delete_policy (destructive), purge_queue (destructive), reset / force_reset / stop_app / shutdown (destructive), clear_password / clear_permissions (destructive). add_user / set_user_tags / set_permissions / change_password (mutating), rabbitmqadmin publish (mutating). list_* / status pass through.
  • NEW — etcd destructive-ops detection. del / rm / delete (destructive), compact (destructive — irreversible history loss), member remove + member update (destructive), auth disable (destructive), user/role mgmt grant/revoke/delete (destructive). put / lease grant (mutating). get / watch / endpoint health pass through.
  • NEW — MinIO (mc CLI) destructive-ops detection. mc rm (destructive), mc rb (destructive), mc admin user/policy/group remove/delete/disable (destructive). mc cp / mv / mirror / pipe (mutating), mc admin add/attach/enable (mutating). mc ls / cat / stat pass through.
  • NEW — per-adapter mount smoke tests (16 cases). Every adapter component imports cleanly + renders without crashing for a sample DB: SQLAdapter (PG/MySQL/ClickHouse), MongoDBAdapter (Percona Studio path + standalone CommandAdapter fallback), RedisAdapter, KafkaAdapter, ElasticsearchAdapter, VectorAdapter, Neo4jAdapter, InfluxDBAdapter, BigQueryAdapter, SnowflakeAdapter, RedshiftAdapter, DatabricksAdapter, CommandAdapter. Catches regressions where an adapter file is renamed/deleted or a top-level import breaks.
  • NEW — per-adapter safety-wiring inspection (13 cases). Static raw-source check that 12 of 13 adapters import the canonical SafeEditor primitive (which provides the /validate/ → destructive-op confirm modal). MongoDBAdapter is the one outlier; verified separately that it routes through BrowserPage (the bespoke Mongo Studio with Safe Ops + blast-radius gauge) for Percona clusters OR CommandAdapter (which uses SafeEditor) for standalone Mongo. Either path is safety-wired.
  • NUMBERS — backend tests: 1247 → 1282 (+35). Frontend tests: 138 → 167 (+29). Smoke probe: 60 endpoints (unchanged). Total: 1509 unit + smoke checks per CI run. All green; CI typecheck (both tsconfig.backend.json + tsconfig.app.json strict) passes.
  • GAP STILL DOCUMENTED — starrocks (SQL-shaped but not in SQL_LIKE_TYPES; uses Command adapter), nats / foundationdb / dgraph / surrealdb / druid / pinot (rare engines, Command-adapter fallback). One remaining gap test in destructiveOps.test.ts asserts starrocks falls through with []; tracked but not blocking since these are rarely-deployed engines.
  • NO BREAKING CHANGES — every existing destructive-ops branch preserved; every existing adapter behavior preserved; UI unchanged; route surface unchanged. Pure additive coverage.
v1.34.5 May 2026
  • CONSOLE TEST HARDENING — user asked for "complete smoke and sanity test for console for all engines, end to end every corner from filter to engine console and safe execution". This release adds the missing test coverage. No functional changes — purely a test + smoke-probe expansion to lock the v1.34.4 work in place + catch any future regression.
  • NEW — frontend tests/operations/Console/__tests__/resolveAdapter.test.ts. Comprehensive table of every dbType the app supports (~50 entries) mapping to the right AdapterKind. Covers: MongoDB family (mongodb/mongo/psmdb/percona-mongo/mongodb-atlas/documentdb), PG family (postgres/postgresql/aws-rds/gcp-cloudsql/azure/cockroach/citus/timescale/yugabyte/patroni/cnpg), MySQL family (mysql/mariadb/all cloud variants/pxc/galera/percona-server-mysql), other SQL (clickhouse/mssql/sqlserver/cassandra/scylla), Redis family (redis/keydb/dragonfly/valkey), Kafka (kafka/strimzi), Elasticsearch (elasticsearch/opensearch), Vector DBs (qdrant/weaviate/milvus/chroma/chromadb), Neo4j, InfluxDB, SaaS warehouses (bigquery/snowflake/redshift/databricks — with beta flag verification), and Command-fallback engines (rabbitmq/memcached/etcd/starrocks/minio).
  • NEW — edge case tests in resolveAdapter: empty/undefined/null dbType doesn't throw (falls to Command), case-insensitive matching, cloud-prefixed strings route correctly, every AdapterKind in the union is reachable from at least one dbType branch (catches "added a new adapter, forgot to wire dispatch"), label is non-empty for every result. Plus precedence tests — SaaS warehouse exact-match takes priority over substring branches, mongo branch wins over generic SQL substring.
  • NEW — frontend components/__tests__/HierarchyFilters.test.ts. Pure logic coverage for the v1.34.4 shared filter component: applyHierarchyFilter predicate (filter by org / env / type / instance, instance prefix handling for both `managed:<id>` and direct perconaClusterId, intersection across multiple filters, empty inputs, orphan DBs without organization). Plus the cascading-reset semantics encoded as a pure transform (Org changes → reset Env+Type+Instance; Env → reset Type+Instance; Type → reset Instance; Instance → no further resets) so future refactors of the dropdown handlers can't break the contract.
  • NEW — Console smoke tests in operations.smoke.test.tsx: ConsolePage mounts cleanly in fleet mode, picker shows the safe-mode banner ("Read-only mode default"), filter chrome shows all 4 dropdowns (ORG / ENV / DATABASE / INSTANCE).
  • EXPANDED — backend smoke probe from 45 → 60 endpoints. Every Console route auth-gates: /api/query-playground (root), /databases list, /templates/{postgres,mongodb,redis,kafka,mysql}, /validate/:id, /execute/:id (managed db), /execute-percona/:id, /export/:id, BigQuery (dry-run, datasets), SaaS (dry-run, introspect, metrics).
  • EXPANDED — backend destructive-ops detector tests from 158 → 169. Added Vector DB coverage (Qdrant/Weaviate/Milvus/Chroma): DELETE method destructive, POST/PUT mutating but escalated to destructive when path mentions delete or drop, GET passes through. InfluxDB coverage: DROP MEASUREMENT/DATABASE destructive, Flux `to(bucket: ...)` pipe is mutating, read-only Flux passes through. Plus null/undefined dbType edge case (doesn't crash).
  • GAP DOCUMENTED — destructiveOps.ts has no Kafka branch. Three new tests intentionally assert that Kafka delete-topic / alter-topic + memcached / rabbitmq / etcd commands return [] from detectDestructiveOps. These tests serve as documentation — deleting them requires either implementing Kafka coverage in destructiveOps.ts or making an explicit decision to keep relying on the client-side adapter prompts that the Command-adapter IDE provides for these engines. Tracked for future release.
  • NUMBERS — backend tests: 1236 → 1247 (+11). Frontend tests: 54 → 138 (+84). Smoke probe: 45 → 60 endpoints (+15). Total covered surface: 1385 unit + smoke checks per CI run. All green; CI typecheck (both tsconfig.backend.json + tsconfig.app.json strict) passes.
  • NO BREAKING CHANGES — zero functional code changes; only tests + smoke-probe additions + the AGENTS.md count update.
v1.34.4 May 2026
  • CONSOLE — Org / Env / DB-Type / Instance filters. Console picker had a flat 84-card grid with only a free-text search; users had to scroll/eyeball to find a specific instance. v1.34.4 brings the same hierarchical filter chrome Monitoring has been using since v1.20: pick an Org → narrow to its envs → narrow to a database type → narrow to a specific instance. Cascading reset matches Monitoring exactly (Org change resets Env/Type/Instance; Env change resets Type/Instance; etc.). Free-text search is still there, narrows further within the hierarchy.
  • NEW — components/HierarchyFilters.tsx (shared). Extracted from MonitoringPage's inline implementation into a reusable component so future consumers (Health page picker, Backups picker, etc.) can drop it in for free. Takes a flat list of /api/databases-shaped rows + value/onChange callbacks; computes Org/Env/DB-Type/Instance options with the same logic + same UI as Monitoring. Exports applyHierarchyFilter(rows, value) helper so the consumer doesn't re-implement the filter predicate.
  • CONSOLE FETCHES TWO ENDPOINTS — /query-playground/databases for the actual shell row data (engine adapter, version, environment name) and /api/databases for the filter-chrome metadata (organization + k8sCluster). They share managed-DB ids so the hierarchy intersection is straightforward (allowedIds set). Backends unchanged.
  • BETTER EMPTY STATE — when the hierarchy filters yield zero matches, the empty state explains: "No databases match this combination of filters. Click Clear to widen the selection, or pick a less-restrictive value." Plus a Clear button that resets all four filters in one click. Distinct from the existing "no matches" message for free-text search.
  • SAFE-MODE BANNER STAYED — the existing "Read-only mode default · destructive ops require confirmation" banner at the top is unchanged; this release adds filter chrome + UX polish, not safety changes.
  • NO BREAKING CHANGES — ConsoleDb shape unchanged; /console/:dbId route unchanged; engine-aware adapter dispatch (mongosh/SQL editor/redis-cli/kafka/etc.) unchanged. Only the picker view changed, and only additively.
v1.34.3 May 2026
  • WORKSPACE BUG FIXES — three issues from the user's screenshot: Restore returned 401, Console (Query/Shell) showed all DBs instead of the workspace DB, Health + Intelligence modules rendered the fleet rollup. All fixed.
  • FIX — Restore module removed from the workspace catalog. v1.33 added 'restore' to the catalog speculatively but never created a /restore route or page — the actual restore flow lives INSIDE the Backups page (select a backup → click Restore). Clicking it routed to a non-existent page that 401'd on a stray API call. Removed entirely; type union also dropped 'restore' so a future false-add won't typecheck.
  • FIX — Console (Query/Shell) reads workspace context. ConsolePage was looking up the DB via useParams<{dbId}>() which works for the legacy /console/:dbId route but NOT inside the workspace, where the route is /db/:managedDbId/console (different param name). Now reads useWorkspaceDbId() as a fallback when the URL param is missing, so workspace-mounted Console scopes to the workspace DB on first paint.
  • FIX — Health + Federation + 6 Intelligence modules (Right-Sizing, Compliance, Upgrade Advisor, Playbooks, DR Testing, Capacity) demoted to 'planned' for ALL engines. These are fleet-by-design pages today — they don't support per-DB scoping (no URL params, no workspace context). Showing them as clickable in the workspace meant clicking opened a fleet view with all 84 DBs which broke the user's mental model. They now show greyed with a "soon" badge so users know per-DB versions are on the roadmap (real implementation = v1.35+). The fleet versions still live in the top sidebar's "Fleet Intelligence" section.
  • CLUSTER_SCOPED_MODULE_IDS trimmed — removed 'health' (no URL-param scoping support) and 'restore' (removed) from the v1.34.2 list. Final list: monitoring, logs, alerts, backups, maintenance, scheduler, transactionTracer.
  • TESTS — +1 frontend test (now 54 total) verifying the v1.34.3 demotion: getCapability returns 'planned' for health + federation + 6 Intelligence modules across PG/MySQL/Mongo. Existing 53 tests still green. Backend tests unchanged at 1236.
  • NO BREAKING CHANGES — fleet routes still live at the same URLs (/right-sizing, /compliance, /capacity-forecasting, etc.); they're still accessible from the top sidebar's "Fleet Intelligence" section; bookmarks don't break. The only change is the workspace sub-sidebar greys those out instead of routing to a fleet view.
v1.34.2 May 2026
  • BUG FIX — workspace dashboard pages were showing the FLEET view (all 84 databases across all engines) instead of scoping to the workspace DB. Reported via screenshot: opening Monitoring inside a PSMDB workspace showed the org-wide rollup with 84 DBs of every type. Same problem on Logs / Alerts / Health / Backups / Maintenance / Scheduler / Transaction Tracer.
  • ROOT CAUSE — the v1.33 workspace navigation correctly routed to the dashboard pages but didn't pass any URL params, so the pages rendered their default fleet view. Picker pages (Index Janitor, Schema Doctor, etc.) got workspace-context auto-fill in v1.33; dashboard pages didn't.
  • FIX — minimum-touch: the dashboards already supported `?cluster=<perconaClusterId>` and `?env=<k8sClusterId>` URL params for filtering (used by the legacy "View in Monitoring" buttons on the All Databases detail panel since v1.6). The workspace sub-sidebar now appends those params automatically when building the nav link for a cluster-scoped module. Zero changes to the 12,163 LOC of dashboard pages.
  • NEW — lib/buildWorkspaceModulePath() and CLUSTER_SCOPED_MODULE_IDS set in DatabaseWorkspaceLayout. The 9 cluster-scoped module IDs (monitoring / logs / health / alerts / backups / restore / maintenance / scheduler / transactionTracer) get the URL param appended; the others (Optimize family, Console, Diagnose, Intelligence per-DB views, Objects) don't need it because they read WorkspaceContext directly.
  • NEW — WorkspaceDb interface gets `k8sClusterId` and `perconaClusterId` fields. DatabaseWorkspaceLayout fetches them from /api/databases (which already exposed them via spread) and the new buildWorkspaceModulePath uses them to construct the right URL.
  • NEW — FleetScopeWarning banner. Direct-Connection-only databases (no perconaClusterId, no k8sClusterId) still can't scope these dashboards — the dashboards key off cluster IDs and a Direct Connection isn't a cluster. The banner explains why the page is showing the fleet view + suggests using the workspace's Optimize/Console pages which DO scope to the DB directly.
  • PRIORITY — perconaClusterId is preferred over k8sClusterId because the dashboards' primary filter is `?cluster=`. K8s env filter is the fallback for K8s-discovered DBs that aren't Percona-operator-managed (CloudNativePG, Crunchy, etc).
  • NO BREAKING CHANGES — fleet routes (/monitoring without query params, etc.) still work exactly as before. Workspace nav links just got smarter about constructing the URL. Tests unchanged (1236 backend + 53 frontend). Smoke probe unchanged at 45 endpoints.
v1.34.1 May 2026
  • CI FIX — unused-import lint errors broke the v1.33.1 + v1.34.0 builds. The CI typecheck (frontend/tsconfig.app.json) is stricter than my local frontend typecheck — it sets noUnusedLocals/noUnusedParameters which my pre-commit doesn't enforce, so the v1.33.1 sidebar trim left 6 unused lucide-react icon imports in Layout.tsx (Wrench / Archive / Calendar / Gauge / Code2 / Stethoscope) that compiled fine locally but failed on push. v1.34.0 also had 2 unused imports in ObjectsPage.tsx (toast, cn).
  • FIX — dropped the 8 unused imports. Local typecheck now uses `npx tsc -p frontend/tsconfig.app.json --noEmit` (matches CI) so this class of regression is caught pre-push.
  • FIX — added the CI typecheck command to the AGENTS.md release process. Before tagging, run BOTH `npx tsc -p tsconfig.backend.json --noEmit` AND `npx tsc -p frontend/tsconfig.app.json --noEmit` (NOT just `cd frontend && npx tsc --noEmit` which uses the looser tsconfig.json).
  • NO FUNCTIONAL CHANGES — nothing else changed vs v1.34.0. If you got v1.34.0 working through some other channel, you can stay on it; v1.34.1 only differs in import-cleanup.
v1.34.0 May 2026
  • NEW — Objects browser in the database workspace. Engine-aware read-only catalog views: Tables for Postgres + MySQL family, Collections for MongoDB family. The OBJECTS section is the new top entry in each workspace's sub-sidebar (visible above Observe). Closes the original v1.33 ask's "show all the modules" piece — you can now actually browse the schema, not just run analyzers against it.
  • POSTGRES — lists every user table (top 500 by size) with schema/name/estimated rows/total bytes/index bytes/has-PK badge/total scans. Click a row to expand: full column list (name, type, nullable, default expr, PK + FK badges), full index list (name, columns, unique, primary, bytes, scans-since-reset), full FK list (columns, referenced table, columns, ON DELETE/UPDATE rules). All from pg_class + pg_attribute + pg_index + pg_constraint catalog reads — never user data.
  • MYSQL — lists user tables from information_schema.TABLES (top 500 by data+index length) with same row shape (schema, name, rows, bytes, hasPK, engine). Detail panel showing columns/indexes/FKs lands in v1.34.1 — needs information_schema.COLUMNS + STATISTICS + KEY_COLUMN_USAGE plumbing similar to PG's. Top-level summary works today.
  • MONGODB — lists collections in the chosen database (default `admin`, picker lets you switch) with estimated docs/total bytes/index bytes/index count/capped flag. Click to expand: full index list (name, key spec, unique/sparse/TTL flags), JSON Schema validator if any, and a "field shape" sample (FIELD NAMES + TYPES from one document, NEVER values — server-side strips them before responding so user data can't leak through this UI).
  • NEW — services/objectBrowser/index.ts. Sibling to the existing services/objects/ (which is the v1.11 CRUD-admin registry). Pure read-only catalog queries that take a v1.30 access object (DbAccess for PG, MysqlAccess for MySQL, MongoAccess for Mongo) so SSH-tunnel + SOCKS-proxy + kubectl-exec all work transparently — same auth + transport plumbing as the rest of the v1.30+ Optimize family.
  • NEW — routes/operations/objects.ts. Five endpoints, all auth-gated, all read-only:
  • GET /api/db/:managedDbId/objects/tables → PG/MySQL top-level table list
  • GET /api/db/:managedDbId/objects/tables/:schema/:name → PG table detail (columns + indexes + FKs)
  • GET /api/db/:managedDbId/objects/collections?database=<name> → Mongo collection list
  • GET /api/db/:managedDbId/objects/collections/:name?database=<name> → Mongo collection detail
  • Identifier validation: schema/name/collection params must match /^[A-Za-z_][A-Za-z0-9_$.\-]*$/ and be ≤128 chars (defense-in-depth on top of pg_quote_ident + JSON.stringify; rejects anything that could break out of quoting).
  • CAPABILITY MATRIX — engineCapabilities.ts gets a new 'objects' module + 'objects' sub-section category. Per-engine status:
  • postgres / mysql / mongodb — supported
  • redis — planned (keyspace browser via SCAN; needs careful pagination)
  • kafka — planned (topic browser + partition state)
  • cassandra / clickhouse / etc. — not in matrix yet (workspace currently shows nothing for these)
  • WORKSPACE NAV — OBJECTS appears above Observe in the per-DB sub-sidebar. Hidden when the engine's capability is not-applicable; shown greyed with "soon" when planned (Redis + Kafka).
  • TESTS — +2 frontend tests (now 53 total): Objects supported for PG/MySQL/Mongo + planned for Redis/Kafka, Objects appears in the workspace sub-sidebar. Backend tests unchanged (1236; the new endpoints are wired into the smoke probe instead of having their own unit tests since they're just thin route handlers around the catalog SQL). Smoke probe expanded from 43 to 45 endpoints — new objects routes auth-gate cleanly with a bogus managedDbId.
  • NOT YET (v1.34.1+) — MySQL table detail (columns + indexes + FKs panel — currently shows summary only with a "lands in v1.34.1" message in the detail expand), Redis keyspace browser, Kafka topic browser, Cassandra keyspace browser. Per-table PII scan + classification mode is its own design — not on the roadmap yet.
  • NO BREAKING CHANGES — this is purely additive. Existing workspace pages, capability matrix, route layer all unchanged. The new services/objectBrowser/ module is intentionally separate from services/objects/ (the v1.11 CRUD admin) so neither overwrites the other.
v1.33.1 May 2026
  • WORKSPACE POLISH — closes the asset-first workflow loop. v1.33.0 introduced the per-database workspace + sub-sidebar; v1.33.1 trims the duplication that came with running both old + new sidebars side-by-side, and adds an environment-first entry point so users go Environments → (browse DBs in this env) → DB → workspace.
  • TOP SIDEBAR TRIMMED — Optimize, Lifecycle, and Diagnose sections removed from the always-visible top sidebar. Those modules live ONLY in the database workspace at /db/:id now — which is the right home for them since they're per-database tools. The top sidebar becomes fleet-mode-only: Overview / Management / Observability / Console / GitOps / Fleet Intelligence (Cost + Compliance + Right-Sizing + Capacity + Engine Migration + Upgrade Advisor + Playbooks + DR Testing + Tracer) / Admin. No more "I can reach Index Janitor from two places" confusion.
  • BACKWARDS COMPAT — the fleet routes (/optimizer/indexes, /backups, /maintenance, /scheduler, /diagnose/incident, etc.) ALL keep working unchanged. Bookmarked URLs don't break; pickers still show the full DB list when accessed from those routes. The only change is they're no longer in the top sidebar — you reach them via the workspace.
  • ENVIRONMENT-FIRST ENTRY — K8s cluster detail page (/clusters/:id) gets a prominent "Browse databases in this environment" button that pre-filters /databases?env=:id. Click any DB row → "Open Workspace" → you're in the workspace. Closes the "after environment register, connect to required db" flow from the original v1.33 ask.
  • DEFERRED — Workspace context for Maintenance / Scheduler / Backups picker pages is intentionally NOT in v1.33.1. Those pages use ?cluster=:perconaClusterId URL params (legacy from when only Percona clusters had per-DB pages); plumbing them into the workspace requires translating managedDbId → perconaClusterId, which is its own refactor. Tracked for v1.34.
  • NO BREAKING CHANGES — every existing route still works; every existing bookmark still works; the only surface change is the top sidebar items list. Workspace pages and capability matrix unchanged from v1.33.0.
v1.33.0 May 2026
  • NEW — Database Workspace. Asset-first navigation. The previous sidebar was task-first ("I want to optimize indexes" → pick a DB) which is great for fleet audits but terrible for incident workflows where you're focused on ONE database. Every serious DB tool (pgAdmin, MongoDB Compass, DataGrip, MongoDB Atlas) is asset-first; v1.33 brings the same model to DBHelm.
  • WORKSPACE LAYOUT — click a database from All Databases (or the new "Open Workspace" button on each detail view) and you enter /db/:managedDbId. A context bar shows DB name + engine badge + namespace + status + Exit. A sub-sidebar groups every module that applies to this engine into 6 categories: Observe / Console / Optimize / Lifecycle / Diagnose / Intelligence. Every nested page inherits the DB — no more re-picking it 8 times during a debugging session.
  • ENGINE CAPABILITY MATRIX — frontend/src/lib/engineCapabilities.ts is the single source of truth for which modules apply to which engines. Three states: 'supported' (works today), 'planned' (conceptually applies; rendered greyed with "soon" badge so users know what's coming), 'not-applicable' (autovacuum on Mongo — hidden entirely). Postgres workspace shows everything; MySQL hides autovacuum; Mongo greys the optimizer-family tools we haven't built yet; Redis hides query optimizer/schema doctor entirely.
  • PICKER AUTO-FILL — the 7 picker pages (Index Janitor, Schema Doctor, Autovacuum, Pool Fit, Plan Watch, Query Optimizer, Code Optimizer, Per-table Cost) detect WorkspaceContext via useWorkspacePickerValue() and pre-fill + lock the picker when in workspace mode. The picker UI stays visible (so users see what got selected) but is read-only; tooltip explains "exit workspace to pick another". Existing fleet routes (e.g. /optimizer/indexes accessed from the top sidebar) still show the picker as before.
  • WORKSPACE OVERVIEW PAGE — minimal v1.33.0 landing page when you enter a workspace. Engine summary strip (engine, source, namespace, status) + one card per category with click-through to the most-used tool. Per-DB rich metrics (live connection count, last backup time, recent alerts) come in v1.33.1.
  • BACKWARDS COMPAT — every existing fleet route (/optimizer/indexes, /monitoring, /backups, etc.) keeps working unchanged. Existing bookmarks don't break. The /db/:id/* tree is purely additive. Workspace pages reuse the EXACT same module page components — the only difference is the WorkspaceContext that pre-fills the picker.
  • TESTS — +23 new frontend tests (now 51 frontend total): detectEngineFamily across 6+ engine families + cloud variants + case-insensitivity + unsupported, getCapability for the v1.32 supported set, planned-vs-not-applicable distinctions for Mongo/Redis, workspaceModulesFor + groupedModulesFor filtering + ordering preservation, catalog integrity (unique IDs, valid categories, no leading-slash paths). Backend tests unchanged at 1236.
  • NOT YET (v1.33.1+) — per-DB Overview rich metrics (live counters, last-backup time, recent alerts), per-engine OBJECTS sub-section (Tables/Indexes for relational, Collections for Mongo, Topics for Kafka, Keys for Redis), workspace context for the remaining pages (Maintenance/Scheduler/Federation), per-DB right-sizing/compliance/upgrade-advisor breaking out from the fleet view.
  • NO BREAKING CHANGES — fleet pages unchanged; existing routes unchanged; existing pickers unchanged when accessed without workspace context. The whole release is opt-in via the new "Open Workspace" entry points on the All Databases page.
v1.32.0 May 2026
  • OPTIMIZE — MySQL parity for the family. Index Janitor, Schema Doctor, Pool Fit, Plan Watch, and Per-table Cost now work for MySQL family databases (MySQL, MariaDB, Aurora MySQL, RDS MySQL, Cloud SQL MySQL, Azure MySQL, Percona Server, Percona XtraDB Cluster, Oracle MySQL Operator) in addition to PostgreSQL. Same UI, same picker, same report shape — engine dispatch happens in the route layer so the frontend doesn't need an engine-specific code path. Autovacuum is the only Optimize tool that stays PG-only (autovacuum is a PG concept; MySQL's InnoDB does incremental dirty-page flushing automatically)
  • NEW — services/optimizer/indexJanitorMysql.ts. Detects unused via sys.schema_unused_indexes (the MySQL 5.7+ view derived from performance_schema), duplicate via information_schema.STATISTICS (same column list + same uniqueness on the same table), redundant (one index's columns are a strict prefix of another's), and missing-FK (FK column with no covering index). Per-finding DDL uses ALTER TABLE … DROP INDEX or CREATE INDEX with proper backtick-quoting. Degrades gracefully when sys.schema_unused_indexes isn't accessible (older MySQL or restricted grants)
  • NEW — services/optimizer/schemaDoctorMysql.ts. Four categories: missing-PK (critical — InnoDB synthesizes a hidden 6-byte rowid which hurts replication + tooling), missing-FK-index (mirrors Index Janitor finding), oversized-text (VARCHAR/CHAR/TEXT >= 1000 chars declared), no-stats (UPDATE_TIME stale > 30 days on tables with rows). high-null-col is PG-only because MySQL would need to scan user data for accurate per-column NULL counts
  • NEW — services/optimizer/poolFitMysql.ts. Same 3-sample-1s-apart approach as the PG analyzer but driven by information_schema.PROCESSLIST + performance_schema.global_variables.max_connections. MySQL classification: COMMAND=Sleep → idle (TIME>600 → long-idle); COMMAND in (Locked, Waiting for table flush, Waiting for table metadata lock) OR STATE LIKE ‘Waiting for%’ → waiting; everything else → active. Same fit score (0-100) + recommended pool size + four finding categories (POOL-TOO-SMALL / POOL-TOO-LARGE / MAX-CONNECTIONS-LOW / LONG-IDLE)
  • NEW — services/optimizer/planFingerprintMysql.ts. Engine-aware EXPLAIN tree walker. MySQL's EXPLAIN FORMAT=JSON has a different shape than PG's (query_block / nested_loop / table.access_type / table.key / grouping_operation / ordering_operation / union_result / materialized_from_subquery). Captures access_type + key (index name) + table_name + used_columns count in tree order. Excludes cost_info + rows_examined_per_scan + filtered (those drift without being a regression). Reuses classifyRegression + queryFingerprint helpers
  • NEW — services/optimizer/engineDispatch.ts. Centralized resolveTargetEngine({connectionId | managedDbId}) that loads the row, detects engine via dbType, and returns {engine, dbType, displayName}. Each route calls this FIRST so the engine branch is decided cleanly before opening any access. Saves repeating the family-detection logic across 5 routes
  • PER-TABLE COST — same blended-share formula (70% storage + 30% compute) for both engines. MySQL uses information_schema.TABLES.DATA_LENGTH+INDEX_LENGTH for storage; performance_schema.table_io_waits_summary_by_table for compute (count_read + count_write). Falls back to TABLE_ROWS as a compute proxy if performance_schema isn't accessible — noted in the report's weightingExplanation so the user knows
  • PLAN WATCH — the background job + on-demand "Run now" both go through the same engine-aware dispatcher. addWatch() validates the engine at watch creation; runWatch() detects the engine at run time (so a connection that's been edited is handled correctly) and routes to either PG (queryRaw + sliceJson) or MySQL (query + EXPLAIN column extraction). Plan + cost fingerprints come from the engine-specific helpers
  • FRONTEND — Optimize pickers widened from POSTGRES_FAMILY to OPTIMIZE_SUPPORTED_FAMILY (PG + MySQL union). Empty-state copy and page descriptions updated to mention both engines. Autovacuum keeps a custom connectionFilter to remain PG-only (with a clear "Postgres-only by nature" note in the page header)
  • TESTS — +22 new backend tests (now 1236 backend total). Index Janitor MySQL: unused via sys.schema_unused_indexes (5), duplicate detection, redundant (prefix) detection, missing-FK detection, graceful degradation when sys.* not accessible. Schema Doctor MySQL: missing-PK, oversized-text. Pool Fit MySQL: classifyMysqlSnapshot (Sleep/Locked/Waiting), healthy report, pool-too-small + max-connections-low. Plan fingerprint MySQL: access_type + key extraction, cost-info exclusion (drift tolerance), nested_loop walking, grouping/ordering, hash stability, NO_PLAN fallback, cost extraction. Existing 1214 tests still green
  • NO BREAKING CHANGES — all PG paths are unchanged; this release is purely additive. The route surface is the same (POST /api/index-janitor/analyze etc.) — they just now accept MySQL connections too. The engine field in every report tells you which path ran
v1.31.1 May 2026
  • FIX — K8s container resolution. The Optimize family + Diagnose were failing on real K8s deployments with `unable to upgrade connection: container not found ("postgresql")` because the resolver did `pod.spec.containers[0]` (blind first-container pick) and `pods.find(p.name.includes(dbName))` (blind first-name-match). That broke for three real-world cases:
  • Stale bootstrap / backup / migration job pods. Their pod names include the cluster name and their spec contains the DB container, but they're in `Succeeded` / `Failed` phase — kubelet rejects exec because the container runtime is gone
  • Multi-container pods where the DB is NOT index 0. CloudNativePG ships `[postgres, bootstrap-controller]`; Crunchy Data ships `[database, pgbouncer, pgbackrest]`; Bitnami ships `[postgresql, metrics]`. Old code picked `bootstrap-controller` / `pgbouncer` / `metrics` as the "DB container" and got rejected by kubelet
  • Operator-specific container names. Bitnami chart names it `postgresql`; CloudNativePG names it `postgres`; Crunchy names it `database`; Zalando Spilo names it `postgres`. Without a preference list, the resolver couldn't tell which container was the actual DB
  • NEW — services/k8sPodResolver.ts. Engine-aware container picker with per-engine preference lists (postgres: [postgres, postgresql, database, pg, pg-cluster, cnpg, patroni, spilo]; mysql: [mysql, mysqld, mariadb, mariadb-server, percona-server, pxc]; mongodb: [mongod, mongo, mongodb, mongodb-agent, psmdb]; redis: [redis, redis-server, valkey, sentinel]; kafka: [kafka, broker]) plus a NEVER_PICK denylist (pgbouncer, pgpool, *-exporter, wal-g, pgbackrest, envoy, istio-proxy, etc.) so sidecars are never picked even if their name matches a substring
  • NEW — Pod ranking. Multiple Running pods get sorted by a heuristic: status.phase=Running gets +100; cnpg.io/instanceRole=primary or role=primary gets +50; -0/-1/-rs0 suffix or name including "primary"/"master" gets +10; backup/restore/bootstrap/migration/cron/job in name gets -200. So the picker prefers the actual primary over a backup-job pod with the same naming prefix
  • NEW — Status-aware container filtering. We now check `containerStatuses[].ready` and `state.running` instead of just spec membership. A container that's in the spec but `not-ready` or `not-running` is rejected upfront so we don't see it as available and then fail at exec time
  • NEW — Structured error responses. When no usable pod can be found, the resolver returns the list of candidates it evaluated and WHY each was rejected. Surfaced through Index Janitor / Schema Doctor / etc. as: "No usable Postgres pod for \"my-cluster\" in \"apps\". No usable Running pod found for \"my-cluster\". Evaluated 2 candidate(s). Top candidates: my-cluster-bootstrap (phase=Succeeded, containers=[postgres], pod phase is Succeeded, need Running)"
  • WIRED — openDbAccess (PG K8s mode), openMysqlAccess, openMongoAccess, and the Diagnose resolveDbContext now all go through resolvePodAndContainer. Same fix applies everywhere a K8s-discovered DB is opened
  • TESTS — +25 new backend tests (now 1214 backend total). detectEngineFamily across 5 families plus unsupported. Container picker tests for: Bitnami chart name, CloudNativePG (skip bootstrap-controller), Crunchy (skip pgbouncer + pgbackrest), Pending bootstrap pod skipped in favor of Running primary, Succeeded backup-job pod skipped, NEVER_PICK denylist, fallback to single running container with custom name, substring match (prod-postgres-primary), primary-by-cnpg.io label, not-ready container rejected, MySQL (mysqld + mariadb), MongoDB (mongod + mongodb-agent), structured error formatting
  • NO BREAKING CHANGES — the resolver falls back to "the only running container" if no name matches the engine preferences, so custom-named pods with a single container still work. The diagnose page still shows ALL name-matching pods (including Pending / Failed) so users can see what's happening; the `container` field is now correctly resolved per-pod instead of always being containers[0]
v1.31.0 May 2026
  • DIRECT CONNECT — SSH tunnel + SOCKS proxy. Many production databases sit behind a bastion/jumpbox (private RDS in a VPC, on-prem servers, corporate VPN). The Direct Connection form now has two collapsible sections that mirror what tools like Studio 3T and DataGrip offer:
  • SSH Tunnel — host / port / username / auth mode (Private Key OR Password) / private key (PEM textarea) / passphrase. ssh2 opens a session to the bastion, then forwards a random local port through the SSH connection to the real DB host:port. The DB driver connects to localhost transparently. Tunnel is closed when the DB connection is torn down
  • Proxy — SOCKS5 / SOCKS4 / HTTP. SOCKS5 is fully wired across pg / mysql / mongo (mongo via native proxyHost option in the driver, pg/mysql via a pre-opened socket through socks). HTTP CONNECT is reserved for future native-driver support
  • NEW — services/connectionTunnel.ts. Two pure-config extractors (extractSshConfig + extractProxyConfig) that validate input shape and decrypt credential blobs, plus runtime helpers (openSshTunnel + socksConnect + openConnectionTunnel). Lifecycle is owned by callers: TcpPgAccess / TcpMysqlAccess / TcpMongoAccess all chain tunnel.close() into their .end() so nothing leaks
  • SSH AUTH — supports both private key (PEM contents pasted into a textarea, optional passphrase) and password modes. Encrypted with the same envelope as DB credentials — same AES-256-GCM, same scrypt KDF, same audit-log redaction. We never log the key or passphrase
  • SCHEMA — 5 additive nullable columns on direct_connections: use_ssh_tunnel, ssh_auth_mode, ssh_credentials_encrypted, use_proxy, proxy_type, proxy_host, proxy_port, proxy_credentials_encrypted. The legacy ssh_key_encrypted column from an earlier UI iteration stays for migration; new code reads ssh_credentials_encrypted (which can hold {password, privateKey, passphrase} together). PRAGMA-introspect-then-ALTER migration block in db/index.ts so existing installs upgrade cleanly
  • AUTH — SSH + proxy creds are stored encrypted; the GET /api/direct-connections list endpoint returns hasSshCredentials / hasProxyCredentials booleans (NOT the blobs themselves) so the UI can show “set / not set” state without ever sending secrets back to the client
  • CONNECTION TESTER — the Test Connection button now opens the SSH tunnel first (if enabled), then probes localhost:tunnelPort, then closes the tunnel. Returns 502 with a clear message if the tunnel itself fails (“SSH tunnel failed: All configured authentication methods failed”), separated from a DB-side failure
  • TESTS — +24 new backend tests (now 1189 backend total). extractSshConfig (10): null when disabled, password mode, key mode with passphrase, port-default 22, legacy sshKeyEncrypted fallback, authMode inference, missing-host / missing-user / missing-creds rejection. extractProxyConfig (7): null when disabled, SOCKS5 with/without auth, type-default, host/port validation, unsupported-type rejection. rewriteMongoUrlHost (6): no-auth URL, user:pass@ preservation, query string preservation, port-less URL, mongodb+srv:// rejection (DNS SRV doesn't make sense to tunnel), unrecognized URL pass-through. Existing 1165 tests still green
  • NOT YET — SSH tunnel currently flows through the optimizer family (Index Janitor, Schema Doctor, Autovacuum, Pool Fit, Plan Watch, Query Optimizer, Code Optimizer, per-table cost) + connection tester. Other touch points (Federation, Console, Migration Engine, Compliance) still use direct host:port. Tracked for v1.31.1
  • NO BREAKING CHANGES — useSshTunnel + useProxy default to false; existing connections keep their behavior. The form sections are collapsed by default; users only see them if they enable
v1.30.0 May 2026
  • OPTIMIZE — Query Optimizer + Code Optimizer become K8s-aware. v1.29 closed the gap for the Doctor family (Index Janitor, Schema Doctor, Autovacuum, Pool Fit, Plan Watch, per-table cost). v1.30 closes the same gap for the Query/Code Optimizer pair across all 3 supported engines (Postgres, MySQL, MongoDB). The Optimize section is now 100% K8s-aware end to end
  • NEW — Engine-specific access abstractions. Three parallel patterns to the v1.29 DbAccess (which is now PG-only and one of three):
  • DbAccess (Postgres) — TcpPgAccess via pg.Client OR KubectlExecPgAccess via `psql -t -A -c "SELECT json_agg(...) FROM (...) t"`. Now supports parameterized queries: TCP path passes them to libpq; kubectl-exec path inlines them with safe pg-quoting (E’…’ string syntax with backslash escaping, \xHEX::bytea for buffers, ’…’::timestamptz for Date)
  • MysqlAccess (new) — TcpMysqlAccess via mysql2/promise OR KubectlExecMysqlAccess via `mysql -B -e "…"` (tab-separated output parsed back to row objects, with mysql’s \n / \t / \\ escaping unescaped on read). Parameter inlining via `?` placeholder substitution that respects single/double/backtick string boundaries (so a `?` inside `‘foo?’` is left alone)
  • MongoAccess (new) — TcpMongoAccess via MongoClient OR KubectlExecMongoAccess via `mongosh --quiet --eval "print(JSON.stringify(…))"`. Two methods (runCommand + listIndexes) sized to what the contextGatherer + future Mongo optimizer features actually use. Collection-name validation prevents shell injection through the eval expression
  • ORCHESTRATOR — The optimizer now resolves the target FIRST (Direct Connection or managed DB), detects the engine, then opens the matching access type. Same code path runs against TCP or kubectl-exec. The optimizer’s safety guards (single-statement EXPLAIN, no ANALYZE, destructive-op classifier on the OPTIMIZED query before showing it) are unchanged — the new code surface only changes HOW we connect, not WHAT we run
  • FRONTEND — Query Optimizer + Code Optimizer pickers now list both Direct Connections AND K8s-discovered databases (filtered to optimizer-supported engines: PG / MySQL / Mongo families) in optgroups. Updated empty states with both “Add a Direct Connection” and “Connect a K8s cluster” links
  • TESTS — +57 new backend tests (now 1165 backend total). Coverage:
  • pgQuoteLiteral (10 tests) — NULL / boolean / number / NaN-rejection / string with embedded backslash + single-quote / Date / Buffer / unsupported-type rejection
  • inlinePgParams (8 tests) — placeholder replacement, two-digit `$10`, out-of-range rejection, $$…$$ dollar-quoted block skipping (so `$1` inside a function body is left alone), single-quote escaping in string params, null param handling
  • parseTsv / mysqlQuoteLiteral / mysqlInlineParams (24 tests) — mysql -B output parsing including literal "NULL", CRLF line endings, escape unescaping, header-only handling; quote literal for all supported types; placeholder replacement that respects string-literal boundaries (`?` inside `‘foo?’` left alone) and backslash escapes
  • isMongoFamily / assertValidMongoCollName / sliceMongoshJson (15 tests) — dbType matching including substring, collection-name allowlist (rejects shell-dangerous chars: ; | & ` $ ( ) \ " ’, null bytes, leading-digit, length cap), mongosh banner stripping for clean JSON parsing
  • NO BREAKING CHANGES — Existing TCP / Direct Connection workflows keep working unchanged. New code path is opt-in via the unified picker. Existing 1108 tests still pass
  • NEXT — With this release, every tool in the Optimize section works for both source types. Future-tracked: AppliedDDL panel (track DDLs the user actually ran via Console), cross-engine optimization suggestions, multi-statement script optimization
v1.29.0 May 2026
  • OPTIMIZE — K8s-discovered databases. Index Janitor, Schema Doctor, Autovacuum Pressure Map, Pool Fit, Plan Watch, and per-table cost attribution all now accept either a Direct Connection (TCP via pg.Client) OR a K8s-discovered Postgres pod (kubectl exec psql). Same UI, same outputs, same DDL — just with a unified picker that lists both source types
  • NEW — Unified DbAccess abstraction. Two implementations behind one interface (TcpPgAccess + KubectlExecPgAccess). The kubectl path automatically wraps every SELECT in `SELECT json_agg(row_to_json(t)) FROM (...) t` so we get back a single JSON array we can parse into the same {rows} shape pg.Client returns
  • PLAN WATCH — schema additive. New nullable `managed_database_id` column on `query_plan_watches` (mutually exclusive with `connection_id`). Background re-EXPLAIN job and on-demand “Run now” both work for K8s-targeted watches
  • AUTH — openDbAccess does the same org-scoping as every other K8s-only route. Cross-org access returns 404 (not 403) so we don’t leak existence
  • TESTS — +18 backend tests (1108 total)
v1.28.1 May 2026
  • Diagnose: full engine-specific signal coverage for Postgres / MySQL / MongoDB / Redis. v1.28.0 collected pod logs + DB log files + (Mongo only) FTDC. That meant for a Postgres lock storm or a MySQL InnoDB deadlock the LLM was staring at log lines but missing the gold (pg_stat_activity, SHOW ENGINE INNODB STATUS). v1.28.1 fixes that
  • NEW — Engine signal collectors. Each runs ~6 engine-specific commands in parallel and bundles results into the LLM prompt with structured per-signal labels + descriptions. All read-only catalog/admin commands; all best-effort (a missing extension or a permission failure surfaces as "ERROR: <reason>" on the individual signal, the bundle continues with the rest):
  • Postgres (6 signals): pg_stat_activity (active sessions with wait events) · pg_locks with blocked-by graph (the lock-storm signal) · pg_stat_replication (per-replica byte+second lag) · pg_stat_statements (top 20 by total exec time, if extension loaded) · pg_settings highlights (the 14 settings most likely to explain incident shape: max_connections, shared_buffers, autovacuum, statement_timeout, etc.) · pg_stat_database (per-DB connection count, cache hit ratio, deadlock count, temp file usage)
  • MySQL (6 signals): SHOW PROCESSLIST (active sessions, sorted by Time desc) · SHOW ENGINE INNODB STATUS (the single most useful MySQL diagnostic dump: latest deadlock, transaction list, semaphore waits, buffer pool, log sequence numbers — 100KB cap because it can be huge) · SHOW REPLICA STATUS (Seconds_Behind_Source, IO+SQL thread state, last error) · SHOW GLOBAL STATUS (the 20 counters most useful for incident triage: thread/connection counts, slow queries, InnoDB lock waits + deadlocks, tmp tables, open file handles) · SHOW VARIABLES highlights (14 settings: max_connections, innodb_buffer_pool_size, durability flags, slow_query_log, packet/temp table caps) · performance_schema events_statements_summary_by_digest top 20
  • MongoDB (5 signals — plus the existing FTDC time-series): db.currentOp (up to 100 active ops with namespace, query, running time, lock-wait flag) · replSetGetStatus (full member state with per-member optime + lag + election term) · curated db.serverStatus() (connections, opcounters, asserts, lock counts, WiredTiger cache + concurrent-transaction tickets, network IO) · connPoolStats (internal pool counts — connection leak / pool exhaustion to other shards) · listDatabases (user DBs with on-disk sizes)
  • Redis (6 signals): INFO ALL (every section: server, clients, memory, persistence, stats, replication, cpu, commandstats, latencystats, cluster, keyspace) · SLOWLOG GET 50 · CLIENT LIST (per-client age, idle, last-cmd, sub state) · MEMORY STATS (per-allocator + jemalloc fragmentation ratio + RSS overhead) · LATENCY HISTORY for the event loop · DBSIZE per logical DB (0..15)
  • PROMPT ORDER — engine signals are placed BEFORE pod logs in the user prompt because they're the highest-density diagnostic per byte; the LLM should see the structured commands before wading through unstructured logs. Same prompt-budget squeeze applies (drop lowest-priority sections first to fit USER_PROMPT_MAX)
  • UI — the Diagnose page's "Raw signals collected" panel adds an "Engine-specific signals" collapsible block listing every command we ran with its label + description + size + per-command click-to-expand (full text in a code block). So you can verify exactly what the LLM saw beyond the log streams
  • TESTS — +15 new backend tests (now 1090 backend total): detectEngineFamily across all 4 family flavors and "unsupported" engines (Cassandra, Elasticsearch, Kafka, ClickHouse, ""), truncateSignal preserving line boundaries, shQuote handling embedded single quotes + spaces + special chars, all 4 engine collector modules export the expected functions (validates module graph), buildUserPrompt with engine signals (correct header + per-signal block + ordering: engine signals BEFORE pod logs)
  • ENGINES STILL OUT OF SCOPE FOR ENGINE-SPECIFIC SIGNALS — Cassandra (nodetool), Kafka (kafka-* CLI tools), Elasticsearch (cluster API), ClickHouse, etc. They're still useful in Diagnose because pod logs + DB log files work for any container; we just don't have the curated diagnostic-command bundle for them yet. Tracked for future releases as we ship deep adapters for each
  • NO BREAKING CHANGES — schema unchanged; existing /api/diagnose/incident response shape is additive (new `engineSignals` field). Existing K8s-only constraint, 24h window cap, BYO-key requirement all unchanged
v1.28.0 May 2026
  • NEW SECTION — Diagnose. A 10th top-level sidebar section with one page (Incident RCA at /diagnose/incident) that turns "something broke at 3am" into a structured Root Cause Analysis with evidence and concrete next actions
  • INCIDENT RCA pipeline (/diagnose/incident): pick a K8s-discovered database + an incident time window (max 24h) + optionally narrow to specific pods. Backend collects three signal streams in parallel — (a) pod logs via kubectl logs --since-time, filtered to the window client-side because K8s has no --until; (b) the engine's own log file via kubectl exec sh -c "tail -c 256k <path>" with engine-specific path search (Postgres /var/lib/postgresql/data/log, MySQL /var/log/mysql/error.log, MongoDB /var/lib/mongo/mongod.log, Redis); (c) for MongoDB, a live FTDC snapshot via db.adminCommand({getDiagnosticData:1}) which gives ~5 minutes of host CPU/mem + serverStatus + replSetGetStatus in one round-trip
  • LLM analysis: the bundle is sent to your configured AI provider (BYO key — OpenAI / Anthropic / Ollama, same SSRF allowlists as the optimizer pipeline). Prompt is engine-aware and bounded to ~30K tokens; oversized log slices are truncated keeping the tail (most-recent entries are most relevant for incident RCA). Response is structured JSON with: summary, rootCause.hypothesis + confidence (low/medium/high), contributingFactors[], evidence[] (every claim must quote a verbatim log line + cite source), recommendedActions[] (each with urgency immediate/soon/followup), missingSignals[]
  • EVIDENCE-DRIVEN by design: the system prompt instructs the LLM that every claim must be supported by a verbatim quote from the bundle, and the UI renders the evidence panel directly underneath the verdict so the user can verify each citation against the raw log lines we surface in collapsible panels
  • HONEST about limitations: low-confidence verdict surfaces "what additional signals would tighten this RCA" so users know what to enable next time (slow query log, metrics-server, etc.). The page footer documents exactly what we collect and how, so SREs aren't guessing what the AI saw
  • SAFETY: read-only — only kubectl logs / kubectl exec sh -c "tail -c N" / db.adminCommand(getDiagnosticData) calls. Never queries your application data; never mutates anything in the cluster. Window length capped at 24h. LLM call has 120s timeout. Per-pod log byte cap (200KB) + total prompt cap (~110KB) prevent runaway token spend on a chatty cluster
  • NEW LLM call wrapper (services/diagnose/llmCall.ts): the existing AI provider abstraction returns a {query, explanation} pair tuned for the optimizer / AI assistant. RCA needs a different shape, so we call OpenAI / Anthropic / Ollama directly with system+user → raw text → our own JSON schema. Reuses the SAME app_settings rows for credentials/model/baseUrl AND the SAME urlSafety SSRF allowlists — just a different output parser. ~70 LOC of duplication that isolates the diagnose pipeline from the security-sensitive optimizer pipeline
  • TESTS — +31 new backend tests (now 1075 backend total): parseLineTimestamp (ISO-8601 + Postgres formats), filterByWindow (in/out of window + unparseable lines kept), truncateKeepingTail (line-boundary preserved + marker injected), buildSystemPrompt (JSON schema in prompt + evidence requirement), buildUserPrompt (metadata header + pod/dbLog/FTDC formatting + USER_PROMPT_MAX enforcement on huge inputs), parseRcaResponse (clean JSON + ```json fences + prose-wrapped + missing required fields + invalid enum coercion + evidence excerpt cap). +1 frontend smoke test (now 28 frontend total)
  • BACKEND SMOKE RUNNER — now probes 43 endpoints (was 42), all green
  • SCOPE BOUNDARIES (deferred to v1.29+) — (1) Direct Connect databases (RDS / Atlas / VMs): need cloud log APIs (CloudWatch / Atlas Logs API / SSH); v1.28 is K8s-only because we use kubectl exec. (2) Historical FTDC files: live FTDC gives ~5 min; the on-disk binary files in /var/lib/mongo/diagnostic.data/ require implementing MongoDB's chunk format (BSON header + zlib payload + delta reconstruction) which is its own project with a proper test corpus. (3) Streaming progress: the page shows static phase hints during the multi-second collection; WebSocket-based phase updates are next
v1.27.0 May 2026
  • "Plan Watch" release — ships the deferred EXPLAIN regression watch as the 8th and final entry in the Optimize section. Register a query, DBHelm re-EXPLAINs it every 30 minutes (and on demand), fingerprints the plan tree shape, and alerts when Postgres starts using a different access path or the EXPLAIN cost jumps ≥2× with no shape change. Catches the post-deploy / post-migration "everything's slow now" class of bugs <em>before</em> your customers do
  • NEW MODULE — Plan Watch (/optimizer/plan-watch): the deferred feature from v1.26 lands. Two-layer fingerprinting: QUERY fingerprint (literal-stripped + normalized hash, so `WHERE id=5` and `WHERE id=10` are the "same query") + PLAN fingerprint (normalized plan-tree shape hash that captures node types + index names + sort/group keys but EXCLUDES costs and row estimates). When the plan fingerprint changes vs the previous run, OR the EXPLAIN cost jumps ≥2× with the same plan shape, the new run is flagged as a regression with a one-line diff explanation ("Plan shape changed: Index Scan using foo_pkey → Seq Scan", "Cost jumped 5× (450 → 2250). Same plan — usually means table grew faster than stats updated.")
  • NEW SCHEMA — query_plan_watches table (one row per registered watch: connection, label, query text, query fingerprint, enabled flag) + query_plan_runs table (one row per re-EXPLAIN: plan fingerprint, total cost, full EXPLAIN JSON, regression flag + reason, prev fingerprint + cost for diff). Foreign-key cascade so deleting a watch cleans up its history. Indexes on watch_id + ran_at + is_regression for fast "find recent regressions" queries
  • NEW BACKGROUND JOB — jobs/planWatchJob.ts. Every 30 minutes (configurable), iterates all enabled watches, runs the same logic the on-demand /run endpoint runs (re-EXPLAIN, fingerprint, classify, store). Serial — one watch at a time — so we don't hammer customer DBs. Disabled when DBHAPP_DISABLE_JOBS=1 (used by the smoke harness so boot doesn't try to talk to real DBs). Once a day, prunes runs older than 90 days
  • NEW SAFETY — every watch query is gated by the existing assertSingleReadOnlyStatement from explainRunner BOTH at insert time (so a multi-statement / DDL / transaction-control query can't even be added as a watch) AND at every run (defense in depth). EXPLAIN itself never executes the actual query — only EXPLAIN (FORMAT JSON, BUFFERS false, VERBOSE false) runs
  • NEW UI — list view shows every watch with last-run status, regression count over the last 24h, total run count, and on-demand "Run now" button. Each row expands to show the watched query + a vertical timeline of every run with regression markers and "copy plan JSON" for inspection. Top KPIs: total watches, enabled count, 24h regression total (turns amber when >0), total runs across all watches
  • TESTS — +32 new backend tests (now 1044 backend total): full coverage of normalizeQuery (string + numeric + scientific literals replaced; comments stripped; whitespace + operators normalized; IN-list collapsed; trailing semicolon trimmed; semantically-different queries stay different), queryFingerprint stability across literal changes, planShapeString (node type + index name + recursion + cost-exclusion), planFingerprint stability + change detection (Seq Scan → Index Scan, index swap, costs ignored), totalCost extraction, classifyRegression (none / plan-changed / cost-spiked / plan-and-cost / custom factor / divide-by-zero), planDiffSummary (top-level swap, index switch, index disappear). +1 frontend smoke test (now 27 frontend total)
  • BACKEND SMOKE RUNNER — now probes 42 endpoints (was 41), all green
  • NO BREAKING CHANGES — schema is purely additive; no migration of existing data. The Optimize sidebar grows from 7 → 8 entries (still inside the no-scroll budget on a default-height window). All existing routes + URLs unchanged
v1.26.0 May 2026
  • "Optimize section completes" release — ships THREE new Postgres-native diagnostic tools (Schema Doctor, Autovacuum Pressure Map, Pool Fit) plus per-table cost attribution. The Optimize sidebar now has 7 entries: Query Optimizer / Code Optimizer / Index Janitor / Schema Doctor / Autovacuum / Pool Fit / Cost — a complete one-stop performance toolkit
  • NEW MODULE — Schema Doctor (/optimizer/schema): finds tables-without-primary-keys, foreign keys with no covering index, columns with ≥80% NULL, oversized text columns (declared text/varchar(255+) when actual data is <32 chars), and tables that have NEVER been ANALYZE'd. Each finding ships with the exact ALTER TABLE / ANALYZE / DROP COLUMN / CREATE INDEX statement. Read-only — only catalog tables (pg_class, pg_index, pg_constraint, pg_stats) are queried. Severity escalates with row count: missing PK on a 50K-row table is critical; missing PK on a brand-new empty table is info
  • NEW MODULE — Autovacuum Pressure Map (/optimizer/autovacuum): the killer Postgres feature most SaaS monitors don't do well. Six categories: BLOAT-EXTREME (50%+ dead tuples → VACUUM FULL), BLOAT-HIGH (20-49% → autovacuum scale_factor tuning), STALE-STATS (>30 days since ANALYZE), NEVER-VACUUMED (autovacuum disabled or unable to reach), HIGH-WRITE-RATE (>1M updates+deletes → FILLFACTOR + autovacuum tuning), and the WRAPAROUND emergency check (xid_age >1.5B = STOP traffic + VACUUM FREEZE). Each finding ships with the exact tuning DDL. Findings auto-sorted with critical first
  • NEW MODULE — Pool Fit (/optimizer/pool): samples pg_stat_activity 3 times one second apart (configurable) to find your real peak active connections vs configured max_connections, then returns a Fit Score (0-100) and a recommended pool size (2-3× peak active). Catches POOL-TOO-SMALL (waits or near-cap utilization), POOL-TOO-LARGE (idle:active >5×1 → wasted DB memory), MAX-CONNECTIONS-LOW (recommendation: ≥3× peak active), LONG-IDLE (>25% idle for >10 min → leaked connections / missing health checks). Snapshots panel shows what we observed at each sample so you can see whether the score is stable or noisy
  • NEW PANEL — Per-table cost attribution on the Cost page: drilldown panel where you pick a Postgres connection and the monthly $ figure from the breakdown above, and we allocate that cost across tables using a blended share — 70% storage (table size / DB size) + 30% compute (table scans / total scans). So a 1MB hot table that gets scanned 100K times/day still gets a real slice. Top 50 tables ranked, with size + scan count + storage % + compute % + blended % + $/mo per row. Powered by pg_total_relation_size + pg_stat_user_tables
  • STORAGE TIER LADDER — new GET /api/schema-doctor/storage-tier endpoint scans every provisioned cluster's config and recommends gp2 → gp3 (AWS RDS, ~20% cheaper at same size), io1 → gp3 when IOPS demand is low (~30-50% cheaper), and PD-SSD → PD-Balanced for typical Cloud SQL OLTP workloads (~30% cheaper). Pure-spec analysis — no DB connection needed; reads from the existing rate-cards lookup
  • NEW SHARED UI — frontend/src/pages/operations/_shared/doctorUI.tsx factors out the repeated "picker + analyze button + filter bar + finding card" pattern across all five Doctor pages (Index Janitor + Schema Doctor + Autovacuum + Pool Fit + future tools). Each new Doctor page is now ~150 lines instead of ~400
  • TESTS — +23 new backend tests (now 1012 backend total): 5 schemaDoctor (missing-PK severity scaling, no-stats, high-NULL with severity gradient, missing-FK index detection, clean-schema), 7 autovacuumDoctor (50%+ bloat critical, 20-49% bloat warning, wraparound emergency 1.5B+, wraparound warning 800M-1.5B, stale stats >30d, healthy table 0 findings, severity sort), 6 poolFit (healthy pool, pool-too-small >=90%, pool-too-large 5×1 ratio, long-idle >25%, multi-snapshot peak detection, pool size recommendation 2-3×), plus 5 storageTier tests (gp2→gp3, io1 low-IOPS→gp3, io1 high-IOPS skip, pd-ssd→pd-balanced, no-recommendation). +4 new frontend smoke tests (now 26 frontend total)
  • NO BACKEND BREAKING CHANGES — every existing endpoint unchanged. The new /api/schema-doctor/* and /api/postgres-doctor/* routes follow the same auth + connection pattern as Index Janitor (org-scoped Direct Connection, statement_timeout, fresh PG client per request, only catalog reads). Backend smoke runner now probes 41 endpoints (was 36), all green
  • DEFERRED — EXPLAIN regression watch (fingerprint plans over time, alert on changes after deploys) deferred to a future release. Needs persistent fingerprint storage + a scheduled job + an alerts pipeline; bigger than a single-session ship and worth doing properly
v1.25.0 May 2026
  • "Optimize section expanded" release — ships the new Index Janitor module, makes Cost Intelligence aware of your whole fleet (not just clusters DBHelm provisioned), and improves the empty-state UX on Query Optimizer
  • NEW MODULE — Index Janitor (/optimizer/indexes): surfaces unused, duplicate, low-usage, and missing-FK indexes across a connected Postgres database with the exact DROP INDEX / CREATE INDEX statement to apply. Read-only — reads pg_stat_user_indexes / pg_stat_user_tables / pg_index / pg_constraint catalogs only, never your data. Findings are ranked by severity (critical / warning / info) and bytes reclaimed; "unused" findings auto-downgrade to Info if the stats collector was reset less than 7 days ago (so we don't recommend dropping an index just because it's been a quiet morning). Generates DROP INDEX CONCURRENTLY DDL so applying is safe in production. "Copy all DDL" button bulk-copies every recommendation as a script you can paste into Console
  • Index Janitor categories: (a) UNUSED — idx_scan == 0 over the stats lifetime, excluding primary + unique keys (those carry semantics beyond ordered access); (b) DUPLICATE — column-prefix overlap detection (one index whose columns are a strict prefix of another's, on the same table; the shorter one is redundant); (c) LOW-USAGE — used in <0.1% of all table accesses, only flagged when there's enough activity (1000+ scans) to judge confidently; (d) MISSING-FK — foreign-key constraints with no covering index (slow joins + slow ON DELETE CASCADE)
  • COST INTELLIGENCE — the dashboard previously only counted clusters DBHelm itself provisioned (provisioned_clusters table). Most users have a fleet of K8s-discovered + Direct-Connect databases that DBHelm did NOT provision — those silently showed $0.00. Now /api/cost/breakdown unions THREE sources: provisioned clusters (richest config), K8s-discovered managed_databases (synthetic provider k8s-discovered → K8s-default rate per replica + storage), and standalone Direct Connections (surfaced with a clear "needs metadata" reason rather than $0). Dedupe logic prevents double-counting where a managed_db row links back to a provisioned cluster
  • NEW PROVIDER — cost estimator now recognizes provider="k8s-discovered" (synthetic, set by the cost route when reading discovered fleet) and provider="direct-connect". Both fall back to honest reasoning when exact instance class isn't known: K8s-discovered gets the per-replica K8S_DEFAULT rate; Direct Connect surfaces the database without a fake $ figure and explains how to attach metadata for accurate estimates
  • BUG FIX — Query Optimizer empty state. When a user has zero Direct Connections (e.g. their fleet is K8s-discovered only), the dropdown was empty with no explanation. Now shows an amber banner explaining that the optimizer needs a Direct Connection (it opens a TCP connection for the safe EXPLAIN runner) with a CTA to /direct-connect. K8s-discovered DB support for the optimizer (via kubectl exec, like Transaction Tracer) is on the v1.26 roadmap
  • TESTS — +9 tests (now 989 backend total): 8 unit tests for the Index Janitor (unused detection with stats-age confidence downgrade, duplicate column-prefix detection, missing-FK detection, low-usage threshold, primary/unique exclusion, all-clean case). +1 frontend smoke test for the Index Janitor page (now 23 frontend tests total)
  • No schema migration; no API contract change to existing endpoints; existing /api/cost/breakdown response shape is unchanged — the breakdown just contains more rows now
v1.24.2 May 2026
  • Patch release: fixes a misleading "Failed to fetch data" toast on Transaction Tracer + makes the new 9-section sidebar collapsible
  • BUG FIX — Transaction Tracer surfaced a generic "Failed to fetch data" toast whenever you picked a database that wasn't a K8s-discovered Postgres / MySQL / MongoDB / Redis cluster. Two real causes underneath: (1) the picker showed ALL databases including Direct-Connect ones, but the backend tracer requires kubectl exec into a real pod, so the moment you selected one it returned HTTP 503 "Cannot connect to database pod"; (2) for K8s clusters that weren't one of the 4 supported engines (e.g. Kafka, Cassandra), it returned HTTP 400 "Unsupported database type". Both were swallowed by an empty catch and rendered as the same useless toast
  • New behavior: the database picker now filters to ONLY the engines + topologies the tracer actually supports (K8s-discovered Postgres / MySQL / MongoDB / Redis families). Picker shows engine type next to the name. If the filtered list is empty, the page renders an explainer instead of an empty dropdown. The remaining error path (e.g. transient pod connectivity) now surfaces the actual backend message ("Cannot connect to database pod", "Failed to get active transactions: <reason>") so you know what to fix
  • BUG FIX — Transaction Tracer Active + Slow Queries tabs were silently empty even when the backend returned data. Cause: the frontend was reading `data.queries` from the API response but the backend has always returned `data.transactions`. Locks + Connections tabs were unaffected (those keys matched). Now reads the correct key
  • NEW UX — Sidebar sections (all 9 of them) are now collapsible with a chevron next to each section header. Click a section title to collapse / expand. Collapsed state is persisted per-section in localStorage so "I always keep Admin collapsed" sticks across reloads. Whichever section contains the page you're currently on is always force-expanded so you can see where you are. Default on first install: every section expanded
  • No backend changes; no schema migration; no API contract change
v1.24.1 May 2026
  • Sidebar reorganization. Operations was a 15-item dump that scrolled off the bottom of a 13" screen — you'd have to scroll just to see Alerts. v1.24.1 splits it into focused 2-7 item sections so every entry is reachable without scrolling on a default-height window. Same URLs, same backend, same code organization underneath — only the sidebar grouping changed
  • NEW SIDEBAR LAYOUT — 9 sections, all 2-7 items each:
  • Overview (2): Dashboard, All Databases
  • Management (4): Environments, Direct Connect, All Clusters, DB Users
  • Observability (4): Monitoring, Health Check, Logs, Alerts — the "is everything OK?" tools
  • Console (2): Console, Federation — the "run a query" tools
  • Optimize (3): Query Optimizer, Code Optimizer, Cost — the "make it faster/cheaper" tools
  • Lifecycle (4): Engine Migration, Backups, Maintenance, Scheduler — the "change data/structure" tools
  • GitOps (2): Declarative, GitOps log — the "reproducibility" tools, pulled out of Operations
  • Intelligence (7): Playbooks, DR Testing, Right-Sizing, Compliance, Upgrade Advisor, Capacity, Trx Tracer
  • Admin (4): Settings, Plugins, Audit Log, Access
  • PRESERVED — every existing URL still works (/monitoring, /optimizer/query, /backups, etc.). No bookmarks broken. No backend changes. No API contract changes. The route table in App.tsx is unchanged — only navSections in Layout.tsx was rewritten
  • MARKETING — Hero.astro mock-app sidebar updated to mirror the new in-app structure with the same section names (Management / Observability / Optimize / Intelligence) so what visitors see on the marketing site matches what they see after install
  • DESIGN RATIONALE — sections are now grouped by what the user is trying to *do* rather than by which file lives where. AI-powered tools (Query Optimizer, Code Optimizer) sit next to Cost under "Optimize" because all three are about making things measurably better. Backups + Maintenance + Scheduler are under "Lifecycle" because they change the data/structure of what already exists. Day-to-day diagnostic tools (Monitoring, Health Check, Logs, Alerts) are under "Observability" because they answer "is everything OK?" without changing anything
v1.24.0 May 2026
  • Code-organization release. No new product features and no behavior changes — every visible page and API surface from v1.23.3 is unchanged. The whole codebase has been re-grouped into module/sub-module folders, dead code is gone, and a real frontend test harness + backend smoke-test runner now ship in the repo so the bug class that hit v1.23 (a frontend page calling a path the backend doesn't serve) gets caught before release
  • BACKEND REORG — 35 route files moved from a flat backend/src/routes/ into routes/{auth,overview,operations,management,intelligence,admin}/ subfolders that mirror the in-app sidebar. backend/src/index.ts now imports from the new paths in module-grouped blocks. Internal `../db`, `../middleware`, `../services` imports inside the moved files are rewritten to `../../`. Dynamic `import()` paths inside scheduler / monitoring / browser / auth handled too. backend/src/jobs/schedulerRunner.ts updated to point at routes/operations/maintenance.js. All 981 existing backend unit tests still pass with zero edits
  • FRONTEND REORG — 33 page directories moved from a flat frontend/src/pages/ into pages/{auth,overview,operations,management,intelligence,admin}/{Feature}/ structure. App.tsx lazy() imports rewritten + grouped. Three relative imports that crossed the new module boundary (Databases, Backups, Monitoring/GenericMonitoringTabs) converted to the @/ alias to stay stable through depth changes. Empty pages/ConnectionStrings/ removed. Frontend production build succeeds with zero errors
  • NEW — Frontend test harness: Vitest + React Testing Library + happy-dom installed as devDeps, vitest.config.ts + src/test/setup.ts wired in, npm test / npm run test:watch / npm run test:coverage scripts added to frontend/package.json. 22 module smoke tests landing across all 6 modules (auth, overview, operations, management, intelligence, admin) verify each page imports without throwing and renders into the DOM. The Compliance / Migrate / Optimizer pages now have explicit smoke coverage so the v1.23.x API/UI mismatch bugs would have been caught here
  • NEW — Backend smoke runner (scripts/smoke-test.ts, npm run smoke): boots a real Express app on a test port against a temp SQLite DB, then HTTP-probes all 36 mounted /api/* base paths. Treats 401/403/404 as PASS for auth-gated reads (we send no token), 200 as PASS for /api/health, and any 5xx or connection-refused as FAIL. Catches the exact bug class from v1.23.0 (frontend page calling /api/connections — a route the backend never had — and getting "API endpoint not found" toast). Currently green: 36 / 36 endpoints reachable
  • DEAD CODE — removed 46-line `tool.slug === 'topology'` mockup block from website/src/pages/intelligence.astro (orphaned by the v1.23.3 fold). Renamed `tool.slug === 'migration'` conditional to `'upgrades'` to match the renamed Upgrade Advisor entry (the EOL radar visualization was correct, just the slug was stale). Removed POST /api/migrate/infer endpoint (zero UI callers; /plan returns the same inference payload as part of its response)
  • NAMING — frontend MigrationAssistant/ folder + MigrationAssistantPage component renamed to UpgradeAdvisor/ + UpgradeAdvisorPage to match the v1.23.3 product naming. Route /upgrade-advisor is the canonical path; /migration-assistant kept as a Navigate redirect so old bookmarks survive
  • No schema migration; no API contract change beyond the documented /migrate/infer removal; existing frontend bookmarks all still resolve (via redirects where needed). Mac DMG + Win .exe + Linux .AppImage + .deb all rebuild cleanly through the v1.22-fixed @xmldom/xmldom 0.8.x electron-builder path
v1.23.3 May 2026
  • Patch release: removes a confusing naming collision (two features both called "Migration") and folds Topology into Monitoring to declutter the Intelligence sidebar
  • NAMING FIX — Intelligence "Migration Assistant" → "Upgrade Advisor". This feature has always been about same-engine version upgrades (Postgres 14 → 16, MongoDB 6 → 7) with EOL detection + breaking-change pre-flight checks. Calling it "Migration" overlapped with the cross-engine data mover at /migrate and made the sidebar ambiguous. Sidebar label, page H1, and marketing copy all updated. The route /migration-assistant is preserved for backward compatibility
  • NAMING FIX — Operations "Migrate" sidebar label → "Engine Migration". Page H1 + intro reworded to make it explicit that this is for moving data <em>between</em> different database engines (MySQL → Postgres today; Mongo → Postgres + DynamoDB → Postgres on the roadmap), and to point users at Upgrade Advisor for same-engine version bumps
  • STRUCTURE — Topology Visualizer removed from the Intelligence sidebar. The same view is now reachable via a "View Topology" button at the top of the Monitoring page. Standalone /topology route + page kept alive (no broken bookmarks; no lost functionality). Honest reasoning: Topology was K8s-only, overlapped heavily with Monitoring (which already shows replica state), and its core value (engine-aware primary/replica/mongos/broker view) sits more naturally next to live metrics than as a separate "advisor"
  • MARKETING — /intelligence section + JSON-LD + FAQ + pricing now describe 7 advisors instead of 8 (Topology Visualizer dropped from the advisor lineup, with a one-line note that the view is now embedded in Monitoring). Hero mock-app sidebar matches the new in-app sidebar (Topology removed; Migration → Upgrade Advisor)
  • No backend behavior change; no schema migration; no API contract change. /api/topology and /api/migration-assistant continue to serve the same payloads
v1.23.2 May 2026
  • Patch release: fixes "API endpoint not found" toast on the Migrate, Query Optimizer, and Code Optimizer pages
  • BUG FIX — the Direct Connection picker on /migrate, /optimizer/query, and /optimizer/code was calling `GET /api/connections` (a non-existent endpoint) instead of the actual `GET /api/direct-connections` route. Result: the picker dropdown stayed empty and a red "API endpoint not found" toast appeared on every page load. The Migrate and both Optimizer features were effectively unusable in v1.23.0 + v1.23.1 unless you happened to refresh after creating the connection from a different page
  • Root cause: when the Optimizer pages were copy-pasted from the Migrate page in v1.23.0, the wrong-path bug from the Migrate page (which had been latent since v1.17 because the Migrate page was rarely the first page anyone visited) was carried forward into both new pages. All three now use `/api/direct-connections` consistent with the rest of the app
  • No backend behavior change; no schema migration; pure frontend URL fix. Existing connections show up immediately after upgrade
v1.23.1 May 2026
  • Patch release: restores macOS DMG distribution (broken since v1.22.0), closes a Compliance UI/API mismatch surfaced by an internal audit, and tightens marketing copy to match shipped behavior exactly
  • BUILD FIX — macOS DMG distribution restored. v1.22.0 + v1.23.0 GitHub Releases shipped Linux + Windows binaries only because the macos-latest CI runner threw `DOMParser.parseFromString: the provided mimeType "undefined" is not valid` during the electron-builder DMG step. Root cause: the v1.22 security override pinned `@xmldom/xmldom` to `^0.9.10`, but xmldom 0.9.0 made the `mimeType` argument to `parseFromString` mandatory and electron-builder 26's plist 3.1.0 still calls it without one. Fix: cap the override to `>=0.8.13 <0.9.0` (xmldom 0.8.13 carries the same security patches as 0.9.10 — `npm audit` still reports 0 vulnerabilities). Mac DMG + ZIP + blockmaps + latest-mac.yml are back in the v1.23.1 release for the first time since v1.21.0
  • BUG FIX — Compliance Engine policy form was sending check names (auth_enabled / encryption_at_rest / audit_logging / version_supported / replication_factor) and operators (equals / not_equals / greater_than / less_than / contains) that the backend rejects with HTTP 400. New behavior: the form now lists the seven actually-implemented checks (backup_configured / alerting_configured / replica_count / ssl_enabled / max_connections / resource_limits / password_policy) with human-readable labels + tooltips explaining each check's expected value type. Operators are now sent as the API's actual tokens (eq / ne / gt / gte / lt / lte) with their human labels in the dropdown. Hover any check to see what value the rule expects (boolean true/false vs integer)
  • HONEST COPY — marketing /intelligence section + cards + JSON-LD rewritten to match what the eight advisors actually do: Topology / Right-Sizing / Capacity / Tracer cards now mark the K8s-only constraint that the backend already enforces; DR Testing now states RPO is from snapshot age + RTO is a heuristic from replica count (not measured failover); Right-Sizing now describes the waste-% output and explicitly defers $ math to the /cost dashboard rather than claiming a feature that didn't exist; Compliance card now lists the actual seven check types and notes that policies are session-scoped today; Tracer card now states Mongo lock view is global stats and Redis (single-threaded) has no lock graph; Playbooks card now says "session execution history" instead of overclaiming a persistent audit trail
  • No backend behavior changes; no schema migration; no new dependencies
v1.23.0 May 2026
  • "Optimizer" release — two new modules that turn DBHelm from "manage your DBs" into "fix your DBs": the Query Optimizer rewrites SQL/Mongo using live schema context, and the Code Optimizer rewrites application code for DB-interaction anti-patterns
  • NEW MODULE — Query Optimizer (/optimizer/query): paste a query, pick a connected database, click Optimize. Backend introspects live schema (sizes / indexes / column cardinality), runs a safe read-only EXPLAIN (never ANALYZE — your query is never executed), and calls your configured AI provider with the full context. Returns: optimized query, plain-English explanation, index suggestions with exact CREATE INDEX DDL + tradeoff notes (write cost / storage), warnings, EXPLAIN-cost comparison where supported, and the destructive-op classification of the rewrite (so the UI can warn before apply)
  • Engine-aware best-practice hints baked into the prompt for 14 dialects: Postgres (LATERAL / partial+BRIN indexes / EXISTS-vs-IN / keyset pagination), MySQL (covering indexes / EXPLAIN FORMAT=JSON warnings / IN-list batching), MongoDB (ESR rule for compound indexes / projection-only covered queries / cursor-pagination), Snowflake (clustering keys / result cache / column pruning), Databricks (Z-ORDER / Photon-friendly UDF avoidance), BigQuery (partitioned+clustered / approximate functions / WITH-CTE materialization), Redshift, Cassandra (ALLOW FILTERING red flag + denormalize-at-write), SQL Server (covering indexes via INCLUDE), Oracle (bind variables for cache hits), Db2, Redis (SCAN over KEYS / pipelining / Lua atomicity), Kafka, Elasticsearch (filter context + doc_values)
  • Safe-EXPLAIN runner: hard refusal on multi-statement queries (defense against `; SET ; DROP TABLE` patterns), refusal on transaction-control + DDL grants, hard refusal on nested EXPLAIN ANALYZE in pasted queries (defense in depth in case a future engine evaluates the inner one). PostgreSQL EXPLAIN parser surfaces seq_scan / sort_spill_to_disk / nested_loop_high_rows / cartesian_join red flags. MySQL parser surfaces using_filesort / using_temporary / full_table_scan / block_nested_loop
  • Live schema gatherer: Postgres (pg_class + pg_attribute + pg_stats + pg_index for table size, columns, cardinality, partial-index predicates, index sizes), MySQL (information_schema.TABLES / COLUMNS / STATISTICS), MongoDB (collStats + indexes() command). Per-table failures don't fail the whole call — partial context is still useful. Hard cap of 20 referenced tables per request
  • NEW MODULE — Code Optimizer (/optimizer/code): paste application code in any of 12 languages (TS / JS / Python / Java / Go / Ruby / C# / PHP / Rust / Kotlin / Scala / SQL), optionally link to a connected DB for engine-aware suggestions. Returns categorized issue list (performance / safety / security / maintainability) with severities (low/medium/high/critical), rewritten code, unified diff, plain-English explanation. Engine-specific anti-pattern hints for 14 dialects
  • NEW SECURITY — Code-paste credential redaction: before code reaches the AI provider, redactCredsFromCode walks the snippet and replaces 8 categories of credential patterns with [REDACTED] (password / pwd / passwd / secret / token / apiKey / privateKey assignments; URL-embedded creds like postgres://user:pass@host; Bearer tokens in headers; OpenAI sk- keys; AWS AKIA*+ASIA* access keys; PEM private key blocks). Redaction count is surfaced to the user so they know we sanitized something
  • NEW SAFETY — Optimizer-specific guardrails: 50K char query cap, 60K char code cap, 1K char intent cap (bounds AI cost), max 50 table hints per call, refusal of nested EXPLAIN ANALYZE, refusal of multi-statement EXPLAIN. All inputs validated before any DB or AI call
  • AUTH model: both routes require auth + org-scoped Direct Connection access (matches the v1.22 /api/migrate model: cross-org returns 404 to avoid leaking existence). The optimizer NEVER applies its rewrite — the user copies the optimized query and runs it through the existing safe Console (which has the destructive-op confirm gate). Defense in depth at every layer
  • Provisioning + monitoring + backups + federation + declarative + cost + migration capabilities all unchanged from v1.22.0 — this release pure-adds two new top-level modules
  • +70 unit tests (981 total): isSafe* + redactCredsFromCode (all 8 credential pattern categories + multi-cred-in-one-snippet + does-not-redact-username), engineForDbType (all 14 engine families), extractReferencedTables (FROM / JOIN / UPDATE / DELETE / INSERT / quoted idents / Mongo db.collection.find / db.collection() patterns), formatTableForPrompt (size formatting / null + cardinality + partial-index predicate / no-indexes case), buildQuerySystemPrompt (engine-specific hints surface), buildQueryUserPrompt (schema context / EXPLAIN inclusion / 4K truncation), buildCodeSystemPrompt (engine hints + JSON-only enforcement + hallucinate-API ban), assertSingleReadOnlyStatement (multi-statement / transaction-control / DDL rejection), parseSchemaQualified (3-part names / quoted idents / whitespace)
  • No new dependencies. Reuses the existing AI provider abstraction (OpenAI / Anthropic / Ollama with v1.22 SSRF allowlists), the existing destructive-op classifier, and the existing AI safety pipeline
  • Sidebar: "Query Optimizer" + "Code Optimizer" added to Operations group
v1.22.0 May 2026
  • "Security hardening" release — closes a full-spectrum security audit (2 critical, 4 high, 6 medium findings). After v1.22.0, npm audit reports 0 vulnerabilities and the SSRF + authz holes that an internal review surfaced are sealed
  • CRITICAL FIX C1 — Operator Hub SSRF: any authenticated user could previously pass an arbitrary `manifestUrl` to /operators/:id/install and the backend would fetch it then apply the parsed Kubernetes objects to the cluster. New behavior: HTTPS-only, host allowlist (raw.githubusercontent.com, github.com, strimzi.io, k8ssandra.io + every catalog host), 8 MiB body cap, manual redirect handling with per-hop revalidation, 30s timeout, embedded-credentials block. Override of `manifestUrl` now requires super-admin role
  • CRITICAL FIX C2 — /api/migrate org/owner authz: previously /infer / /plan / /execute loaded any Direct Connection by id without checking the caller's org. Any authenticated user could exfiltrate data from another org's MySQL by guessing connection ids. New behavior: org-scoped check on every connection load (super-admin bypasses), 404 on cross-org access (no existence leak), and /execute requires write role (super_admin / admin)
  • HIGH FIX H1 — 0 dependency CVEs: bumped Electron 35 → 41.5.1 (closes 17 advisories incl. use-after-free in WebContents, command-line switch injection, response header injection); bumped tar via override (closes 6 path-traversal advisories); bumped @xmldom/xmldom (4 XML injection); bumped basic-ftp / fast-xml-builder / cacache / make-fetch-happen / @tootallnate/once / thrift / better-sqlite3 / uuid. Frontend vite + postcss + follow-redirects all clean. npm audit on root + frontend now reports 0 vulnerabilities
  • HIGH FIX H2 — AI provider baseUrl SSRF + key-theft block: super-admin previously could point AI at any URL and the bearer/x-api-key would be sent there. New behavior: per-provider host allowlists (OpenAI → *.openai.com / *.openai.azure.com / *.azure.com; Anthropic → *.anthropic.com; Ollama → anywhere except cloud-metadata IPs/hostnames); embedded-credentials block; HTTPS-only for OpenAI / Anthropic
  • MEDIUM FIX M1 — Plugin loader symlink escape: a symlinked .mjs in ~/.dbhelm/plugins/ could resolve outside the dir. New behavior: realpath check + reject anything outside the plugin sandbox
  • MEDIUM FIX M2 — Operator manifest YAML loaded with CORE_SCHEMA only (refuses !!js/* custom tags), eliminating the !!js/function eval class of attacks
  • MEDIUM FIX M3 — Cluster-scoped K8s install warning: installOperator now enumerates the cluster-scoped kinds in the manifest (CRDs / ClusterRoleBindings / etc.) and refuses to apply unless the caller passes ackClusterScope=true. Route returns HTTP 409 with the kind list so the UI can prompt for confirmation
  • MEDIUM FIX M4 — Databricks host allowlist: parseDbCreds now requires the host to end with .cloud.databricks.com / .azuredatabricks.net / .gcp.databricks.com / .databricks.com / .databricks.net. httpPath must start with / and not be an absolute URL
  • MEDIUM FIX M5 — Audit-log secret redaction: new redactSecrets() pure helper walks audit `details` and replaces values whose key matches password / passwd / pwd / secret / token / apiKey / privateKey / credential / authorization / bearer / SA_PASSWORD / oraclePwd / encryptionKey patterns. Applied at logAudit boundary so it covers both the persisted audit row AND the GitOps mirror
  • MEDIUM FIX M6 — stateLog git commit hardened: replaced execSync + shell-quoting with execFileSync (no shell at all). Subject + body bounded to 200 / 64K respectively to prevent pathological events from blowing up the git plumbing
  • NEW LIB — backend/src/lib/urlSafety.ts: shared SSRF-safe URL validator (host allowlist + private-IP block + cloud-metadata block + IPv6 + CGNAT 100.64/10) and safeFetchText() with manual-redirect revalidation + body cap + timeout. Used by operator hub today; will be the canonical entrypoint for any future user-supplied URL handling
  • NEW LIB — backend/src/lib/redact.ts: pure redactSecrets() with deep-clone, cycle-break, 18 sensitive key patterns, configurable via patches. 100% covered by tests
  • +76 security tests (911 total): isPrivateOrLoopbackHost across IPv4/IPv6/CGNAT/cloud metadata, assertSafeUrl (scheme / credentials / allowlist / private-IP / subdomain-bypass), redactSecrets (cycle-break, deep-clone, no input mutation, all sensitive key patterns), Operator Hub SSRF (cluster-scoped enumeration, allowedManifestHosts coverage, parseManifest CORE_SCHEMA, rewriteNamespaces preserves cluster-scoped kinds), AI provider URL builders (OpenAI / Anthropic / Ollama allowlists + bypass-attempt rejection), Databricks host allowlist (subdomain confusion + lookalike domain rejection)
  • OPERATIONAL: Electron 35 → 41.5.1 + better-sqlite3 12.9.0 native rebuild verified working. Macos arm64 binary builds clean. Required because Electron 42 broke the better-sqlite3 native binding
  • COMPATIBILITY: existing API surface unchanged for all read paths. /api/migrate now requires Write role for /execute; /operators/install requires ackClusterScope=true when the manifest touches cluster-scoped kinds. Both surface as HTTP 403 / 409 respectively with actionable error messages so the UI can re-prompt
v1.21.0 May 2026
  • "Top-10 closer" — 4th and final phased release that brings the DB-Engines top-10 to 10/10 end-to-end DBHelm parity. Oracle Database + IBM Db2 land
  • NEW PROVISIONER — k8s-oracle: provisions Oracle Database via Oracle's official OraOperator (database.oracle.com/v4/SingleInstanceDatabase). Wizard collects namespace, edition (Express XE free / Enterprise BYOL / Standard BYOL), version (XE 21c / Free 23ai / 19c EE / 21c EE), SID + PDB name (Oracle uppercase rules enforced), storage size + class, CPU/memory requests + limits, optional imagePullSecret for paid editions, and a mandatory Oracle license acceptance checkbox
  • Oracle image routing: Express → container-registry.oracle.com/database/express; Free 23ai → /database/free; Enterprise → /database/enterprise; Standard → /database/standard. Tested image tags pinned in the wizard
  • Oracle resources per cluster: cryptographically random SYSTEM password (24 chars; uppercase + lowercase + digit guaranteed), Secret with key oracle_pwd (operator convention), then the SingleInstanceDatabase CR. Endpoint: oracle://<name>.<ns>.svc.cluster.local:1521/<pdb>
  • NEW PROVISIONER — k8s-db2: provisions IBM Db2 Universal Container via the official Db2u Operator (db2u.databases.ibm.com/v1/Db2uCluster). Wizard collects namespace, edition (Community free / Standard BYOL / Advanced BYOL), version (12.1 / 11.5.9 Community / 11.5.8 BYOL), members (1 / 2-with-HADR / 3-with-HADR), database name (Db2 uppercase rules enforced ≤ 8 chars), storage size + class, CPU/memory requests + limits, optional imagePullSecret for paid editions, mandatory IBM license acceptance
  • Db2 image type routing: community → db2oltp; standard / advanced → db2wh. HADR auto-wired in the CR when replicas > 1. Two PVCs per pod (meta + data) using the storage spec. Endpoint: db2://<name>-db2u.<ns>.svc.cluster.local:50000/<dbname>
  • OPERATOR HUB — 10 first-party operators now installable in one click: + Oracle Database Operator (database.oracle.com/v4 probe, pinned v1.2.1) and IBM Db2u Operator (db2u.databases.ibm.com/v1 probe). All four enterprise relational engines (Oracle / Db2 / SQL Server-via-StatefulSet / Cassandra) now have one-click prereq install
  • Provisioning matrix is now 17 providers — K8s (CNPG, Percona PG, PSMDB, MongoDB Community, MySQL Operator, Redis Operator, K8ssandra, SQL Server, Oracle, Db2, Strimzi) + Cloud (RDS Postgres + MySQL, Cloud SQL Postgres + MySQL, Azure DB Postgres + MySQL Flexible Server)
  • +60 unit tests (835 total): Oracle SingleInstanceDatabase CR shape (image pullFrom edition routing, pullSecrets gating, persistence with optional storageClass, resources requests + limits gating, adminPassword secret-ref to oracle_pwd key), buildOracleImage (express / express+free / enterprise / standard routing), Oracle SYSTEM password (24 chars; upper+lower+digit guaranteed across 20 random rolls), validation matrix (cluster name / namespace / SID Oracle uppercase ≤ 8 / PDB uppercase ≤ 30 / Oracle license / enterprise needs imagePullSecret); Db2uCluster CR shape (license.accept passthrough, image type db2oltp/db2wh routing, 2 PVCs meta + data with optional storageClass, HADR auto-enabled when replicas > 1, podConfig with db2u resources, instance password secret-ref), Db2 password (24 chars alphanumeric only — Db2 reserved-char-free), validation matrix (cluster name / namespace / edition / replicas 1-3 / database uppercase ≤ 8 chars / IBM license / paid editions need imagePullSecret)
  • Top-10 STATUS COMPLETE: 10 of 10 fully covered. PostgreSQL ✅ MongoDB ✅ MySQL ✅ Redis ✅ Cassandra ✅ SQL Server ✅ Snowflake ✅ Databricks ✅ Oracle ✨ IBM Db2 ✨
  • Customer milestone: any customer running anywhere in the DB-Engines top-10 can now run their entire database fleet through DBHelm — from cluster provisioning through day-2 operations — without leaving the desktop app or hiring per-engine specialists
v1.20.0 May 2026
  • "Top-10 coverage round 3" — brings Snowflake + Databricks from "queryable" to "fully manageable." After this release, 8 of the DB-Engines top-10 are end-to-end DBHelm-supported
  • NEW OBJECT ADMIN — snowflakeAdmin: 5 object kinds via standard SQL DDL through the existing snowflake-sdk connection. CREATE WAREHOUSE (5 sizes from X-SMALL to X-LARGE, auto-suspend / auto-resume / multi-cluster scaling, INITIALLY_SUSPENDED for safety), CREATE DATABASE / CREATE SCHEMA (with optional COMMENT), CREATE ROLE, CREATE USER (with PASSWORD + DEFAULT_ROLE + DEFAULT_WAREHOUSE + MUST_CHANGE_PASSWORD on first login)
  • Snowflake identifier safety: every identifier double-quoted to preserve case + prevent injection. Validation enforces the safe identifier alphabet ([A-Za-z_][A-Za-z0-9_]*, ≤ 128 chars) at the input layer before any SQL is built. Listing via SHOW WAREHOUSES / DATABASES / ROLES / USERS
  • NEW OBJECT ADMIN — databricksAdmin: Unity Catalog + SQL Warehouse lifecycle. Catalog + Schema via SQL DDL (CREATE CATALOG / CREATE SCHEMA with optional MANAGED LOCATION + COMMENT, IF NOT EXISTS by default for idempotence). SQL Warehouse via REST API (POST /api/2.0/sql/warehouses) with cluster size (2X-Small → X-Large), warehouse type (PRO / CLASSIC), auto-stop, multi-cluster scaling
  • Databricks identifier safety: backtick-quoted, identical safe alphabet rules as Snowflake. Listing via SHOW CATALOGS + SHOW SCHEMAS IN <catalog> (capped at 5 catalogs to bound API calls)
  • NEW ObjectKind union types: added 'collection' (Mongo), 'user' (SaaS), 'warehouse' (Snowflake / Databricks). The same /clusters → Objects tab UI now handles all 7 kinds depending on cluster type
  • Customer impact: a Snowflake-heavy or Databricks-heavy org can now do their entire account/workspace administration from DBHelm. Create warehouses, databases, schemas, roles, users — all auditable, all going through the destructive-op classifier, all replayable via the GitOps event log
  • +61 unit tests (775 total): Snowflake identifier validation (rejects digit-leading / spaces / dots / dashes / > 128 chars), quoteSfIdent + quoteSfLiteral (escape doubling), all 5 DDL builders (CREATE WAREHOUSE with all params + AUTO_RESUME TRUE/FALSE, CREATE DATABASE/SCHEMA with optional comment escaping, CREATE ROLE, CREATE USER conditional clauses including MUST_CHANGE_PASSWORD only when password set), buildDropSql for all 5 kinds + qualified DROP SCHEMA, validation matrix (warehouse size / autoSuspend 60-3600 / minClusterCount / maxClusterCount ≥ min, schema parent-DB requirement, user defaultRole + defaultWarehouse, unsupported kind rejection); Databricks identifier validation, quoteDbIdent (backticks) + quoteDbLiteral, buildCreateCatalogSql + buildCreateSchemaSql (IF NOT EXISTS, MANAGED LOCATION + COMMENT combinations), buildDropSql (DROP CATALOG IF EXISTS, qualified DROP SCHEMA IF EXISTS, throws on warehouse), buildCreateWarehouseRequest snake_case shape, validation matrix (warehouse name spaces+dashes OK, cluster size allowlist, type allowlist PRO/CLASSIC, max ≥ min, autoStopMins 1-720)
  • Adds no new dependencies. snowflake-sdk + @databricks/sql were already shipped
  • Top-10 status: 8 of 10 fully covered (PostgreSQL ✅, MongoDB ✅, MySQL ✅, Redis ✅, Cassandra ✅, SQL Server ✅, Snowflake ✨ now full, Databricks ✨ now full). Oracle + IBM Db2 land in v1.21
v1.19.0 May 2026
  • "Top-10 coverage round 2" — closes the Cassandra and SQL Server gaps. After this release, 6 of the DB-Engines top-10 are end-to-end DBHelm-supported
  • NEW PROVISIONER — k8s-cassandra: provisions Apache Cassandra via the K8ssandra Operator (k8ssandra.io/v1alpha1/K8ssandraCluster). Wizard collects namespace, Cassandra version (4.0 / 4.1 / 5.0), datacenter name, nodes per datacenter (1–12), storage size + class, CPU/memory limits, and a Reaper auto-repairs toggle (on by default — strongly recommended). Multi-datacenter from day one (DBHelm v1 ships single-DC; multi-DC is a one-line spec edit). Endpoint: cassandra://<name>-<dc>-service.<ns>.svc.cluster.local:9042
  • OPERATOR HUB — added K8ssandra Operator (k8ssandra.io/v1alpha1, pinned to v1.20.0). Bundles cass-operator dependency in the install manifest
  • NEW PROVISIONER — k8s-mssql: provisions Microsoft SQL Server on Kubernetes via a managed StatefulSet. Microsoft's original mssql-operator was deprecated; the StatefulSet path is what Microsoft's docs now recommend for vanilla SQL Server in K8s. No operator install needed. Wizard collects namespace, edition (Developer / Express / Standard / Enterprise), version (2019 / 2022), storage size + class, CPU/memory requests + limits, and a mandatory EULA acceptance checkbox
  • SQL Server provisions 4 K8s resources per cluster: an Opaque Secret with the SA password (cryptographically random, satisfies SQL's 8+ chars / 3-of-4 character classes policy deterministically), a headless Service for stable DNS, a ClusterIP Service for client connections (port 1433), and the StatefulSet itself with a TCP readiness probe. Endpoint: mssql://<name>.<ns>.svc.cluster.local:1433
  • SQL Server explicit limitations: replicas hard-coded to 1 (Always On Availability Groups out of scope for v1); PVCs preserved on remove() for data safety (delete manually for clean wipe); no operator-managed backup CRD ships with this approach — use Velero PVC snapshots, or wire up a sidecar that runs sqlcmd BACKUP DATABASE
  • NEW ENGINE TYPES added to ClusterEngine union: cassandra / sqlserver / oracle / db2 (oracle + db2 land in v1.21)
  • Provisioning matrix is now: 15 providers — K8s (CNPG, Percona PG, PSMDB, MongoDB Community, MySQL Operator, Redis Operator, K8ssandra, SQL Server, Strimzi) + Cloud (RDS Postgres + MySQL, Cloud SQL Postgres + MySQL, Azure DB Postgres + MySQL Flexible Server)
  • +38 unit tests (714 total): K8ssandraCluster CR shape (datacenter spec, storageConfig with optional storageClass, resources gating, reaper auto-scheduling on/off), validation matrix (cluster name / namespace / datacenter name pattern / size 1-12); SQL Server SA password generator (24 chars, all 4 character classes verified across 20 random rolls), saSecretName lower-case + suffix, buildSaSecret (SA_PASSWORD key only), buildMssqlHeadlessService (clusterIP None), buildMssqlClientService (ClusterIP), buildMssqlStatefulSet (image string with version, ACCEPT_EULA + MSSQL_PID + secret-ref env vars, volumeClaimTemplate with optional storageClass, resource requests + limits gating, TCP readiness probe), validation matrix (cluster name / namespace / edition allowlist / EULA acceptance gate)
  • Top-10 status: 6 of 10 fully covered (PostgreSQL, MongoDB, MySQL, Redis, Cassandra ✨, SQL Server ✨). Remaining: Snowflake admin (v1.20), Databricks admin (v1.20), Oracle (v1.21), IBM Db2 (v1.21)
v1.18.0 May 2026
  • "Top-10 coverage round 1" — first of four phased releases that bring DB-Engines top-10 databases to end-to-end DBHelm parity. This release closes the obvious K8s gaps for MySQL and Redis
  • NEW PROVISIONER — k8s-mysql-operator: provisions MySQL Group-Replication clusters via the official Oracle MySQL Operator (mysql.oracle.com/v2/InnoDBCluster). Wizard collects namespace, version (8.0 / 8.4 LTS), server replicas (1–9), MySQL Router replicas (1–5), storage size + class, CPU/memory requests, and root username/host. Generates a cryptographically random root password (you can override) and creates the secret + InnoDBCluster CR. Endpoint: mysql://<name>.<ns>.svc.cluster.local:3306 (MySQL Router handles read/write splitting)
  • NEW BACKUP PROVIDER — mysql-operator-backup: triggers MySQLBackup CRs against an InnoDBCluster. Backup destination (S3 / OCI / persistent volume) configured via .spec.backupProfiles[] on the parent CR; we reference one by profile name when kicking off ad-hoc backups. Logical dumps via MySQL Shell util.dumpInstance() under the hood
  • NEW PROVISIONER — k8s-redis-operator: provisions Redis with Sentinel auto-failover via the Spotahome Redis Operator (databases.spotahome.com/v1/RedisFailover). Wizard collects namespace, Redis version (6.2 / 7.2 / 7.4), Redis replicas (1–9), Sentinel replicas (3–9, odd numbers only for quorum), storage size + class, CPU/memory requests, and AOF persistence toggle. Emits AOF customConfig (appendonly + appendfsync everysec) when persistence enabled. Endpoint: redis-sentinel://rfs-<name>.<ns>.svc.cluster.local:26379
  • OBJECT ADMIN: extended mysqlAdmin to register for k8s-mysql-operator + azure-mysql-flexible alongside the existing aws-rds-mysql + gcp-cloudsql-mysql. Database / role / user creation via the standard mysql2 client now works on InnoDB Cluster + Azure DB MySQL clusters
  • OPERATOR HUB: 7 first-party operators now installable in one click — added MySQL Operator (Oracle, mysql.oracle.com/v2 probe) and Redis Operator (Spotahome, databases.spotahome.com/v1 probe). The all-in-one Spotahome manifest ships CRD + RBAC + operator Deployment together; MySQL Operator install pulls the trunk deploy-operator.yaml
  • Provisioning matrix is now: 13 providers — K8s (CNPG, PSMDB, MongoDB Community, MySQL Operator, Redis Operator, Strimzi, Percona PG) + Cloud (RDS Postgres + MySQL, Cloud SQL Postgres + MySQL, Azure DB Postgres + MySQL Flexible Server)
  • +49 unit tests (676 total): InnoDBCluster CR shape (GVK, secretName ref, datadirVolumeClaimTemplate with optional storageClass, podSpec gating on resources, labels), root credentials Secret (Opaque, rootUser+rootPassword+rootHost keys), sanitizeIdent / rootSecretName / generateRootPassword pure helpers, validation matrix (cluster name / namespace / instances 1-9 / routers 1-5 / username pattern); RedisFailover CR shape (image string, persistent storage, AOF customConfig gating, sentinel replicas), validation matrix (replicas 1-9 / sentinel quorum: odd 3-9); MySQLBackup CR shape + validation
  • No new dependencies. mysql2 + crypto already shipped
  • Top-10 status: PostgreSQL ✅, MongoDB ✅, MySQL ✅ (was partial), Redis ✅ (was missing), Snowflake ⚠️ partial, Databricks ⚠️ partial, SQL Server / Oracle / Cassandra / IBM Db2 still gapped — closing these in v1.19, v1.20, v1.21
v1.17.1 May 2026
  • "MongoDB end-to-end" patch — closes the last gap stopping MongoDB customers from running DBHelm as their entire DBA function. Two new shipping pieces and one new operator catalog entry
  • NEW PROVISIONER — k8s-mongo-community: provisions MongoDB Community via the official MongoDB Inc. operator (mongodbcommunity.mongodb.com/v1). Wizard creates a Secret with the initial admin password (cryptographically random by default) and the MongoDBCommunity CR; operator handles SCRAM credential generation. Use this when you specifically need MongoDB Inc.'s build (compliance, support contracts) — PSMDB remains the recommended path for most teams
  • NEW BACKUP PROVIDER — psmdb-backup: on-demand backups for Percona PSMDB clusters via PerconaServerMongoDBBackup CRs. PBM (Percona Backup for MongoDB) under the hood. Logical or physical backup type. Storage destination configured on the parent cluster (.spec.backup.storages map). Restore via PerconaServerMongoDBRestore CR with optional point-in-time target
  • NEW SCHEDULE PROVIDER — psmdb-backup-schedule: cron-style recurring backups by patching the parent PSMDB CR's .spec.backup.tasks[] array. Multiple tasks per cluster supported. Read-modify-write pattern with JSON-Patch test guards to avoid index-shift races
  • OPERATOR HUB — 5th first-party operator: MongoDB Community Operator (v0.9.0) with one-click install. CNPG / PSMDB / Strimzi / Percona PG / MongoDB Community now all one-click installable from the Operator Hub page
  • Provisioning matrix is now: 11 providers — K8s (CNPG, PSMDB, MongoDB Community, Strimzi, Percona PG) + Cloud (RDS Postgres + MySQL, Cloud SQL Postgres + MySQL, Azure DB Postgres + MySQL Flexible Server)
  • +62 unit tests (627 total): PSMDB backup CR shape (logical / physical / labels / GVK), restore CR shape (in-place vs PITR), validation matrix (storage names, types, names with caps/spaces); PSMDB schedule task builder, JSON-Patch add/remove shapes, find-task-index across malformed inputs, validate (cron + storageName + type + keep range); MongoDB Community Operator CRD shape (SCRAM auth, replica set type, user roles, volumeClaimTemplate with optional storageClass, container resources for both mongod + mongodb-agent), sanitizeIdent (lowercase / dash / truncation), userPasswordSecretName, generatePassword (uniqueness + base64url alphabet)
  • Customer-facing impact: MongoDB Community customers can now do full Day 0 + Day 2 from DBHelm — provision via Community Operator OR PSMDB, on-demand + scheduled backups via PSMDB, restore (in-place + PITR) via PSMDB, object admin (databases / collections / users) via the existing mongoAdmin. The remaining gap (MongoDB Community Operator backup CRD) is upstream — the operator simply doesn't ship one yet
v1.17.0 May 2026
  • "Migration engine v1" — turns the third moat (Tier 2 cross-engine migrations) from concept into shipping product. First pair: MySQL → Postgres
  • Three-click flow: pick a source MySQL Direct Connection, pick a target Postgres Direct Connection, plan, execute. The /migrate page hosts the entire wizard
  • SCHEMA INFERENCE: walks information_schema (TABLES + COLUMNS + STATISTICS) for everything in the source database. Captures column types with full precision/length, primary keys, indexes (unique + composite), and row counts
  • TYPE MAPPING: opinionated, complete, MySQL → Postgres mapping. Unsigned ints widened (smallint→integer, int→bigint, bigint→numeric(20,0)+lossy flag). tinyint(1) detected as boolean. AUTO_INCREMENT PKs become SERIAL/BIGSERIAL. JSON → JSONB. ENUM/SET → TEXT (lossy, flagged). MEDIUMINT/MEDIUMTEXT/LONGTEXT → INTEGER/TEXT. Geometry types → BYTEA. TIMESTAMP → TIMESTAMPTZ. YEAR → SMALLINT. Unknown types fall back to TEXT with a "please verify" warning
  • PLAN PREVIEW: terraform-style table cards showing source→target mapping per column with inline lossy badges. CREATE TABLE + CREATE INDEX DDL inspectable per table. Per-table warning aggregation. Total estimated rows up top
  • EXECUTOR: per-table DDL run on the target (skip-with-warning if the table already exists — we never DROP). Data streams in pages of N (default 1000, configurable 100–10,000). Single multi-row INSERT per page with parameterized placeholders. Per-table error isolation — one failing table doesn't kill the run
  • VALIDATION: per-table source vs target row count after copy completes. Match/mismatch surfaced inline. Sample-checksum validation foundations in place — wired in v1.17.1
  • Schema-only mode: run DDL with no data — useful for pre-creating empty target tables ahead of a real cutover
  • Audit log: every execute logged with sourceConnectionId, targetConnectionId, table count, total rows copied, duration, and schemaOnly flag
  • Routes: POST /api/migrate/{infer,plan,execute}
  • +46 unit tests (565 total): full type-mapping matrix (integer widening, tinyint(1)→bool, decimal precision, varchar bound vs unbounded, datetime/timestamp distinction, json→jsonb, enum/set/spatial lossy flagging, unknown fallback), pgIdent quoting/escaping, generateCreateTable (basic + composite PK + nullable + defaults), generateCreateIndex (unique + multi-column + sanitization), planner (BIGSERIAL detection, lossy aggregation into per-table warnings, targetSchema/prefixTables overrides, empty input)
  • Adds no new dependencies (mysql2 + pg already shipped for direct-connection probing)
  • v1 explicit limitations called out in the UI and docs: foreign keys not migrated, defaults stripped (different SQL between engines), no dual-write cutover yet — lands in v1.17.1
v1.16.0 May 2026
  • "Cost intelligence" release — the second strategic moat from Tier 2 ships. Estimated monthly + annual spend per cluster, no extra cloud credentials needed
  • NEW /cost PAGE: headline tiles (monthly / annual / coverage / top opportunity), per-engine bar chart, per-provider rollup, ranked per-cluster ledger sorted high→low. Each cluster card has a one-line explanation of the math behind the number
  • RATE-CARD ESTIMATOR: pure-data pricing constants for AWS RDS (14 instance classes), Cloud SQL (6 tiers + custom-shape formula at $0.0413/vCPU/hr + $0.007/GB-RAM/hr), Azure DB Flexible Server (8 SKUs), and K8s defaults ($0.05/replica/hr + $0.10/GB-month). Storage priced separately by provider
  • Smart fallbacks: known instance class → rate-card hit. Cloud SQL custom shape → vCPU+RAM formula. Unknown class → "unknown" status with the missing class name surfaced (so you know what to add). K8s clusters → per-replica default. SaaS engines (BigQuery / Snowflake / Redshift / Databricks) → per-query model with a pointer to query history
  • Storage parser supports K8s-style suffixes: "100Gi", "100GB", "1TiB", "1024MiB" all parse correctly
  • Routes: GET /api/cost/breakdown (full payload), GET /api/cost/cluster/:id (per-cluster detail with shape + reason)
  • Sidebar: "Cost" added to Observability group
  • +18 unit tests (519 total): parseStorage (numbers / GB / GiB / Gi / MiB / TB / negative / garbage), per-provider rate-card lookups (AWS RDS r6g, Cloud SQL custom-shape formula, Azure D4s_v3), replica multiplier, deleted/failed clusters cost zero, SaaS bypass, unknown provider fallback, aggregation totals + sorting + per-engine and per-provider rollups
  • No new dependencies. Pure compute against existing provisioned_clusters rows
  • EXPLICIT v1 BOUNDARY: numbers are estimates only, not your real cloud bill. No reservations, savings plans, sustained-use discounts, free tiers, network egress, IOPS, or per-query SaaS spend. Live billing-puller integration (AWS Cost Explorer / GCP Billing API / Azure Cost Management) lands in v1.16.1
v1.14.1 May 2026
  • "GitOps polish" patch — finishes the Tier 1 set with reapply + drift detection, and surfaces v1.14 features that were API-only in the desktop UI
  • GITOPS REPLAY: state-history.jsonl is now reconstructable into a full StateFile at any historical event id. GET /api/state/replay (current) or /api/state/replay/:eventId (point-in-time). Output is the same YAML the declarative engine consumes — so "redeploy what was running last Tuesday" is one click
  • DRIFT DETECTOR: new background job runs every 15 min (configurable via DBHELM_DRIFT_INTERVAL_MS, set to 0 to disable). Compares live state vs. either state-history replay (default) or a desired YAML at DBHELM_STATE_DESIRED_FILE. GET /api/state/drift returns the cached report; POST /api/state/drift/refresh recomputes
  • Drift severity: none / minor (only unmanaged resources) / major (any create / update / delete needed). Pulled into a pure helper so CI can test without pulling in the database
  • NEW /state/history WEB PAGE: vertical timeline of state-changing events with action glyphs (cluster.create / object.delete / schedule.create / backup.restore / operator.install). Drift indicator at the top with severity coloring. Click "Replay to here" — YAML lands in your clipboard, paste into /declarative to apply. "Export current" downloads a YAML of right-now
  • NEW /plugins WEB PAGE (super-admin only): lists every plugin DBHelm loaded from ~/.dbhelm/plugins/ at startup. Status (loaded / skipped / failed), reason-if-skipped, manifest details, links to homepage. The path is shown so you know where to drop new ones
  • Sidebar: "GitOps log" added to the Observability group, "Plugins" added to Admin (gated to super-admins)
  • +16 unit tests (501 total): replay engine (cluster create/delete cascading deletes, object/schedule lifecycle, upToEventId stops correctly, ignore-non-state events, malformed-event tolerance), drift severity classifier (empty / no-change / unmanaged / mixed)
  • No new dependencies. Backend boots drift detector automatically; opt out via env var if you don't want the periodic plan() call
v1.14.0 May 2026
  • "Federation + Declarative state" release — second AND third strategic moats from the roadmap, shipped together. (v1.13.0 Federation rolled into this release after a CI hiccup; auto-updaters skip 1.13 → 1.14)
  • CROSS-ENGINE FEDERATION (was the v1.13 headline): in-process DuckDB attaches Postgres + MySQL Direct Connections as virtual catalogs. Write ANSI SQL across them — joins push down to scanners when they can. 14 engines covered (CNPG / RDS / Cloud SQL / Azure DB / Cockroach / Citus / Timescale / Yugabyte for PG; RDS / Cloud SQL / Azure DB / MariaDB / PXC / Vitess for MySQL)
  • New /federation page: pick connections to attach, get an alias, write SQL, see results. Schema sidebar lists tables across all attached catalogs
  • DECLARATIVE STATE (the v1.14 headline): the Terraform-for-DBs YAML lands.
  • A single state.yaml describes your whole estate: clusters (10 provisioners), objects (databases / roles / schemas / topics), schedules. dbhelm.com/v1 schema versioned for forward compat
  • Plan: terraform-style diff with create / update / delete / unchanged / unmanaged. Per-key diff for updates. Renders in CLI with colored glyphs and in the new /declarative web page
  • Apply: dispatches to the exact same provisioner / object-admin / schedule-provider registries the UI uses. Order: clusters first, then objects + schedules whose parent succeeded. Failures are per-item — apply doesn't abort the whole run
  • Export: dumps current managed state (provisioned_clusters + cluster_objects[createdByUs=true] + backup_schedules) to YAML. Secrets stripped (you re-supply at apply time)
  • CLI: scripts/dbhelm.ts via tsx. Subcommands: validate / plan / apply / export. Designed for CI: exit code is non-zero on any apply failure. Colored output. Optional --out for export
  • Web UI: new /declarative page with side-by-side editor + plan/apply/export panel. Starter YAML pre-populated. Plan diff rendered with the same color scheme as the CLI
  • Audit log: declarative-applied actions get source: declarative in details so you can grep what came from CI vs. a UI click. GitOps event log mirrors them too — full provenance
  • +28 unit tests (482 total): YAML parser (apiVersion / kind / clusters / objects / schedules with cross-reference validation), id-format check, duplicate detection, dump-roundtrip, diffCluster (namespace / region / per-key / password-skip / garbage-tolerance), sameClusterIdentity
  • Routes: POST /api/declarative/{parse,plan,apply}, GET /api/declarative/export, plus /api/federation/{attachable,attached,attach,execute,schema}
  • +52 unit tests across both features (485 total): federation classifier + value normalizer (DuckDB BigInt/List/Struct/Map handling), DSN builders + redaction; declarative parse + diff (cluster identity, per-key diff, password-skip)
  • Deps added: @duckdb/node-api (federation), reused js-yaml (declarative)
  • CI hiccup note: shipped as a single v1.14 tag because v1.13 federation tests transitively dragged in better-sqlite3 (cross-arch native binding). Fix was the same shape as the v1.11.1 emailValidation fix — extracted the pure helpers into their own module
v1.12.0 May 2026
  • "Intelligence" release — first wave of strategic moats from the v1.12+ roadmap
  • AI assistant glued to the safety rails: bring-your-own-key for OpenAI / Anthropic / Ollama (or self-hosted via base URL). Every LLM proposal pre-flighted through detectDestructiveOps + (for SaaS) cost dry-run. Read-only mode blocks AI-generated writes outright. The LLM never auto-executes anything
  • Plugin SDK (@dbhelm/sdk): public TypeScript types for all five extension points (provisioning, backups, schedules, objects, SaaS). Backend loads ~/.dbhelm/plugins/*.{js,mjs} at boot. Failures are isolated. Example MariaDB-demo plugin shipped
  • GitOps event log: state-history.jsonl mirrors every state-changing audit event. Optional DBHELM_STATE_GIT_REPO env var commits each event to a real git repo. Foundation for v1.14 declarative state
  • New routes: GET/PUT/DELETE /api/ai/config, POST /api/ai/test, POST /api/ai/generate, GET /api/plugins, GET /api/state/history
  • Settings → AI assistant panel for super-admins: provider picker, model dropdown per provider, API-key (encrypted), test-provider button
  • Console: "Ask AI to write a query" panel above the editor on every adapter (only renders when a provider is configured). Proposal cards show classification badge, cost preview when available, "Use this query" → editor → existing destructive-confirm flow
  • +44 unit tests (430 total): dialect mapping for 16 engine families, system-prompt builder including read-only enforcement, JSON-with-narration parser, full safety-pipeline matrix (read-only blocks vs warns, cost preview thresholds, dryRun failure tolerance), provider lookup + cost estimator
  • ROADMAP.md committed: full Tier 1–4 sequencing through v1.18 + year-2 moonshots
  • Added semver dep (plugin compatibleWith check)
v1.11.1 May 2026
  • Open registration: removed the gmail-only restriction. Anyone can now register with any valid work or personal email. Optional ALLOWED_EMAIL_DOMAINS env var keeps the allowlist option for operators who want it
  • Email validator: proper RFC-5321 length limits (254 total / 64 local) + a practical regex that matches what mail providers actually accept
  • Login no longer re-validates email format — keeps you signed in if the regex tightens between releases
  • Operator Hub: distinguishes "operator absent" from "kubeconfig invalid" / "credentials unauthorized". Surfaces a per-cluster banner with the right fix path. Per-row pills correctly say "Unknown" when we can't reach the API server (was misleadingly "Not installed")
  • Operator install button is disabled when the cluster itself is unreachable — no point trying
  • Fixed ERR_ERL_KEY_GEN_IPV6 startup warning by routing the rate-limit fallback through ipKeyGenerator() so v6 addresses get normalized to /64
  • README + /docs aligned with actual auth rules: there is NO canned admin/admin, you bootstrap on first launch with an email of your choice and a 12-char password
  • +11 unit tests (386 total): 8 for the new email validator covering allowlist on/off + RFC length limits, 3 for the operator probe classifier covering unreachable / network / catalog shape
v1.11.0 May 2026
  • Restore: point-and-click restore from any completed backup into a brand-new cluster. CNPG (new Cluster CR with bootstrap.recovery + externalCluster ref) and AWS RDS (RestoreDBInstanceFromDBSnapshot)
  • Scheduled backups: new Schedules tab with three adapters — CNPG ScheduledBackup CR (multiple cadences per cluster, K8s/Quartz cron), Percona PG (patches parent cluster's pgBackRest schedules.{full|differential|incremental}), AWS RDS backup window (PreferredBackupWindow + BackupRetentionPeriod via ModifyDBInstance)
  • MongoDB object admin: PSMDB clusters get an Objects tab with database / user / collection wizards. Reads MONGODB_USER_ADMIN_* from the operator-generated <cluster>-secrets
  • MySQL object admin: AWS RDS MySQL + Cloud SQL MySQL get an Objects tab with database + user wizards. SET sql_mode = NO_BACKSLASH_ESCAPES on every connection so our literal escaper is canonical
  • Kafka topics: Strimzi clusters get an Objects tab with KafkaTopic CR creation. Partitions, replicas, cleanup.policy, retention.ms — reconciled by the Strimzi Topic Operator
  • Restored clusters get their own row in /api/clusters and the full Backups + Schedules + Objects experience — the new endpoint chains naturally
  • 63 new unit tests (375 total): CNPG restore CR shape, RDS restore body, ScheduledBackup CR, Percona PG schedule JSON-Patch, RDS window validation (incl. wrap-past-midnight), cron 5/6-field validator, mongo + mysql + kafka builders + identifier escaping
  • Added pg, mongodb, mysql2 as deps. Backup adapter type signature gains optional restore() + restoreCatalog. Schedules registry sits in services/backups/schedules/ with the same registry+catalog pattern
v1.10.0 May 2026
  • Backups & DR: per-cluster Backups tab dispatches to a new BackupProvider abstraction. Adapters ship for CNPG (Backup CR), Percona PG (PerconaPGBackup CR + pgBackRest full/diff/incr), AWS RDS (CreateDBSnapshot), and Strimzi MirrorMaker2 (KafkaMirrorMaker2 CR for Kafka DR replication)
  • In-cluster object management: Objects tab on every Postgres-flavored provisioned cluster (CNPG, Percona PG, RDS, Cloud SQL). Wizards for CREATE DATABASE / ROLE / SCHEMA with proper identifier escaping
  • Credential resolution: CNPG and Percona PG creds come from the operator-generated Secrets via K8s API; RDS / Cloud SQL use the master password we stored at provision time over TLS
  • Spot-check CLI: scripts/spot-check.ts walks every provisioner through validate → loadContext → create → poll → delete against real creds. Two npm scripts: spot-check (dry) and spot-check:create (full lifecycle)
  • Provisioned cluster detail page: status / config / live poll, Backups tab with create + refresh + delete, Objects tab with persisted + observed merge view
  • 52 new unit tests (312 total): backup CRD builders for CNPG / Percona PG / MirrorMaker2, DDL escaping (quoteIdent, quoteLiteral, assertSafeIdentifier), CREATE DATABASE / ROLE / SCHEMA / DROP IF EXISTS shape
  • Backup adapter type signature now allows forClusterProvider to be string | string[] so one adapter can cover related provisioners (RDS Postgres + MySQL share aws-rds-snapshot)
  • Added pg + tsx as deps
v1.9.0 May 2026
  • Five new cluster provisioners: Strimzi Kafka, Percona PG Operator, AWS RDS (Postgres + MySQL), Azure Database (Postgres + MySQL Flexible Server)
  • Operator Hub — one-click install for CNPG, PSMDB, Strimzi, and Percona PG operator manifests on any registered K8s cluster
  • Inline operator-installer banner in the Create Cluster wizard: pick a K8s env and missing operators surface a one-click Install button right there
  • Strimzi: KRaft-only, two-pool topology by default, sane HA defaults (auto-tunes replication factor + min.insync.replicas based on broker count)
  • Percona PG: bundles pgBouncer + pgBackRest with weekly Sunday-01:00-UTC full-backup schedule out of the box
  • AWS RDS: gp3 storage by default, encrypted, Multi-AZ optional, tagged with managed-by=dbhelm
  • Azure: ARM REST API client (no @azure/arm-* SDK needed), token cache, password-complexity validation matching Azure rules
  • 60 new unit tests covering all 5 new provisioners, request shapers, validators, and the operator-manifest parser/namespace-rewriter (260 total)
  • Added @aws-sdk/client-rds and js-yaml as dependencies
v1.8.0 May 2026
  • Spin up new clusters from inside DBHelm (beta): Create Cluster wizard at Environments → Spin up new cluster
  • MongoDB (Percona): unified into the new wizard — same PSMDB CR flow, now with the multi-step UX
  • PostgreSQL (CloudNativePG / CNPG): new provisioner. Single-CRD HA Postgres, 1-5 instances, choice of PG 14 / 15 / 16
  • Google Cloud SQL: new provisioner for both Postgres (POSTGRES_14/15/16) and MySQL (5.7 / 8.0). Auth via the existing GCP service-account Direct Connection
  • Pluggable ClusterProvisioner backend interface (mirrors SaasProvider) — adding RDS / Strimzi / Percona PG next is now ~one new file
  • Unified /api/clusters routes: GET /catalog, GET /environments, POST /, GET /:id (live poll), POST /:id/refresh, DELETE /:id
  • 37 new unit tests covering the CNPG CRD builder, Cloud SQL request shaper, and registry shape (200 tests total)
  • New /docs section: per-engine provisioning guide with prerequisites for the operator install + Cloud SQL Admin API enable
v1.7.0 April 2026
  • Public beta milestone: dbhelm.com is now feature-complete for individual + small-team use
  • License changed to Business Source License 1.1 with 4-year auto-conversion to Apache 2.0 (see /license)
  • New marketing pages: /docs (getting-started + per-adapter guides), /pricing (Community / Team / Enterprise), /status (per-adapter readiness flags)
  • Vitest scaffolding + 163 unit tests covering destructive-op detection across all engines and the SaaS provider registry
  • GitHub Actions CI: lint + type-check (backend, electron, frontend) + unit tests on every push and PR
  • Optional, opt-in error telemetry via Sentry (off by default, scrubs request bodies/cookies/auth headers)
  • Download page: prominent beta + unsigned-binary banner with per-OS workarounds and SHA-256 verification pointer
  • Footer redesign: docs, pricing, license, and live status links
v1.6.14 April 2026
  • Snowflake, Redshift, Databricks deep adapters in Console (beta)
  • Per-provider monitoring dashboards: credits/DBUs, CloudWatch metrics, top queries
  • New shared SaaS provider registry: dry-run + introspection + metrics in one interface
  • Pre-flight EXPLAIN cost preview banner for all three new adapters
v1.6.13 April 2026
  • BigQuery deep adapter: dataset/table tree with row+byte counts, click-to-SELECT, INFORMATION_SCHEMA shortcut
  • Pre-flight cost banner: every query is dry-run first to show bytes-processed and on-demand $-cost before you hit run (warns above $1)
  • New SaaS execution backend using @google-cloud/bigquery SDK, with 2 TB maximum-bytes-billed safety cap per query, service-account auth via Direct Connect, and full destructive-detection + audit-logging parity with the kubectl-exec path
v1.6.12 April 2026
  • InfluxDB 2.x deep Flux adapter: bucket tree with lazy measurement expansion
  • Click bucket or measurement to drop a time-ranged Flux starter into the editor; writes blocked in Read-only
v1.6.11 April 2026
  • Neo4j deep Cypher adapter: graph-schema tree with Labels, Relationship Types, and Property Keys browsers
  • Click any schema entity to drop a matching Cypher starter into the editor
  • Backend: Cypher write-clause detector so Read-only mode blocks CREATE/MERGE/DELETE/SET/REMOVE; vector DBs now classify POST/DELETE properly; InfluxDB catches DROP and to() writes
v1.6.10 April 2026
  • Vector DBs deep adapter: Qdrant / Weaviate / Milvus / Chroma collection browser with flavor-specific similarity-search starters
  • Backend accepts METHOD + JSON body for vector DBs so POST searches now work from the Console (blocked in Read-only)
v1.6.9 April 2026
  • Elasticsearch / OpenSearch deep adapter: index browser with live health, doc count, and store size
  • Click index to prefill match_all search; mapping shortcut for each index; POST/PUT/DELETE gated by Read-only + destructive confirm
v1.6.8 April 2026
  • Kafka / Strimzi deep adapter: topic + consumer-group browser with filter, click-to-describe prefill (partitions, replicas, ISR, lag, offsets, members)
  • --create / --delete / --alter require Read-only off and destructive confirm
v1.6.7 April 2026
  • Redis / KeyDB / Dragonfly / Valkey deep adapter: SCAN-based keyspace browser with DB-number selector, MATCH pattern filter, per-key TYPE badges, TTL chips, and type-aware viewer commands
  • Click a key -> starter command drops into the editor (GET for strings, HGETALL for hashes, LRANGE for lists, SMEMBERS for sets, ZRANGE WITHSCORES for sorted sets, XRANGE for streams)
  • Shared introspection helper so every Console adapter runs browse queries with the same read-only safety flags
v1.6.6 April 2026
  • New Console module unifies Query Playground and DB Studio under a single sidebar entry
  • MongoDB adapter delivers the full DB Studio experience (collection browser, Safe Ops, blast-radius gauge, rollback scripts) for PSMDB clusters
  • Deep SQL adapter with lazy-introspected schema tree and safe SQL IDE — covers Postgres, MySQL, MariaDB, CockroachDB, ClickHouse, MSSQL, Cassandra, Yugabyte, Citus, Timescale, CloudNativePG, PXC, Galera, Patroni
  • Command adapter for Redis, Kafka, Elasticsearch, Neo4j, Influx, etcd, RabbitMQ and vector DBs with DB-type-aware templates and the full v1.6.5 safety + export stack
  • Legacy /query-playground and /browser URLs redirect to /console so existing bookmarks keep working
v1.6.5 April 2026
  • Query Playground: read-only mode (on by default) blocks accidental writes on every DB type (Postgres read-only txn, MySQL read-only session, Redis/etcd/ES/Kafka write-blocking)
  • Destructive query detector + confirmation modal — DROP/DELETE/TRUNCATE/ALTER/GRANT/REVOKE and MongoDB drop/remove/deleteMany/updateMany now require explicit confirmation and are audit-logged
  • Export dropdown with CSV / JSON / NDJSON — both instant (visible rows) and full-result (up to 50k rows) variants using engine-native formats
  • Per-user rate limit (30/min) on query execution, 2 MB raw-output cap, auto-LIMIT on bare SELECTs, smarter shell-escaping
v1.6.4 April 2026
  • New /savings page showing concrete cost savings running DBHelm vs managed DBaaS like MongoDB Atlas, AWS RDS, Confluent Cloud, ClickHouse Cloud, and Aiven (40–70% typical savings)
  • Homepage savings teaser with three real-world scenario cards (MongoDB, Postgres, Kafka) and bottom-line monthly/annual savings
  • Full methodology section with publicly-listed pricing source links for every managed provider — no cherry-picked numbers
  • Added Savings to header nav and footer
v1.6.3 April 2026
  • Fixed Weaviate monitoring: real classes, objects, nodes, properties (previously always 0 due to missing curl/bash in Alpine image)
  • Vector DB monitoring (Weaviate/Qdrant/Milvus/Chroma) now tunnels HTTP through the K8s API-server pod-proxy, works on any minimal/distroless image
  • Added dedicated Qdrant, Milvus, and Chroma engine-metric collectors with collections, cluster, and Prometheus data
  • Fixed ClickHouse real-time queries (replaced invalid JSONObject() SQL with FORMAT JSONEachRow)
  • Fixed StarRocks: no longer reports available=true when zero data was collected; broadened FE/BE/CN pod matching; aligned chart paths
  • Broadened MongoDB credential discovery to cover Bitnami, MongoDB Community Operator, and generic Helm layouts (was Percona-only)
  • Fixed Weaviate Real-Time Pods card that showed 0/0 while K8s reported 1/1
v1.6.2 April 2026
  • Auto-populate GCP project ID, cluster name, and region from kubeconfig during GKE cluster registration — eliminates manual entry errors that caused Cloud Logging failures
  • Frontend kubeconfig parser now detects GCP project from gke-gcloud-auth-plugin exec args in addition to context name patterns
  • Added GCP Project ID format validation on cluster register and update endpoints
v1.6.1 April 2026
  • Fixed monitoring dashboard crash when pod metrics or summary data is unavailable
  • Added 10-15s timeouts to all Kubernetes API calls to prevent indefinite hangs when clusters are unreachable
  • Fixed unsafe JSON.parse on database metadata that could crash the dashboard endpoint
v1.6.0 April 2026
  • Security Hardening: comprehensive vulnerability audit and remediation across all backend endpoints — removed 3 critical, 5 high, and 7 medium severity issues
  • Removed Connection Strings module: eliminated credential exposure risk where live database passwords were returned via API to read-only users
  • Query Playground sandboxing: replaced arbitrary shell fallback with explicit error, added command allowlists for Redis, etcd, Kafka, RabbitMQ, Cassandra nodetool; shell-safe quoting for PostgreSQL and MySQL
  • MongoDB monitoring auth fix: all 4 generic MongoDB monitoring endpoints (Realtime, Query Insights, Performance, Growth) now use getMongoCredentials + TLS detection — fixes blank dashboards on auth-enabled clusters
  • Registration lockdown: post-bootstrap user creation now requires super_admin invitation — anonymous self-registration disabled
  • Authorization hardening: fixed cross-tenant incident report access, resourceAuth bypass for orphan database rows, added requireWrite to health check POST
  • Input sanitization: database name validation, MongoDB JS string escaping, URL path metacharacter rejection, dangerous Redis command blocking
  • Error message redaction: internal error details (stack traces, driver messages, infrastructure paths) no longer returned to API clients across 15+ endpoints
  • Rate limiter fix: removed validation bypass options that weakened per-client IP tracking behind reverse proxies
  • Legacy encryption migration: automatic startup re-encryption of old 3-part ciphertext (static salt) to current 4-part format (random salt per value) using AES-256-GCM
  • Account enumeration prevention: login error messages normalized to prevent email address discovery
  • Monitoring dashboard fixes: dbType alignment for all database families, Weaviate health checks, Prometheus parsing, RabbitMQ connections, Cassandra tpstats, StarRocks queries, MySQL/MariaDB growth data
v1.5.0 April 2026 Intelligence Suite
  • Incident Playbooks: built-in runbook automation with 5 diagnostic playbooks (High CPU, Replication Lag, Connection Exhaustion, Disk Space, Slow Queries) — auto-generates incident reports with findings, severity, and recommendations
  • Database Topology Visualizer: interactive graph view showing primary/replica/arbiter topology with replication edges, health status, and metrics across database, cluster, and global scopes
  • Disaster Recovery Testing: DR readiness scoring (0-100), RPO/RTO calculation, backup freshness analysis, failover simulation (dry-run), and cross-database DR summary dashboard
  • Resource Right-Sizing Advisor: analyzes CPU/memory/storage requests vs actual usage per pod, identifies over/under-provisioned resources, and generates cost-saving recommendations
  • Compliance & Policy Engine: define policies with custom rules, evaluate across all databases, generate compliance reports with pass/fail per policy per database
  • Migration Assistant: detect current database versions, check EOL status, run pre-flight compatibility checks, surface breaking changes and deprecated features before upgrades
  • Capacity Forecasting: linear regression-based projections for storage, memory, and connections — identifies databases approaching capacity with urgency alerts and projected exhaustion dates
  • Multi-Database Transaction Tracer: real-time active queries, slow query analysis, lock contention detection, and connection monitoring across PostgreSQL, MySQL, MongoDB, and Redis
v1.4.0 April 2026
  • Query Playground: execute queries against any of 55+ database types directly from the UI — with syntax templates, EXPLAIN support, result tables, JSON view, and CSV export
  • One-Click Health Check: comprehensive diagnostic reports with scored health assessment, deep engine-specific checks (connections, cache, replication, locks), actionable recommendations, and exportable snapshots
  • New sidebar navigation: Query Playground and Health Check accessible from the main menu
  • Backend support for all database types: MongoDB, PostgreSQL, MySQL, Redis, Elasticsearch, Kafka, Cassandra, ClickHouse, Neo4j, InfluxDB, etcd, and more
v1.3.1 April 2026
  • Deep Percona XtraDB Cluster (PXC) monitoring: full Galera wsrep metrics — cluster state, flow control, certification failures, queue depths, replication stats
  • Percona Server for MySQL (PS): Group Replication member status with host, port, state, role tracking
  • Percona PostgreSQL monitoring: Patroni HA status, streaming replication lag, WAL stats, replication slots
  • Galera-specific Performance Advisor: warns on non-Synced nodes, flow control >1%, certification conflicts
  • PostgreSQL HA Advisor: replication lag, inactive slots, WAL archive failures, Patroni health checks
  • Percona operator badge across Real-time, Query Insights, and Performance Advisor tabs
  • All Percona products now receive first-class deep monitoring on par with PSMDB
v1.3.0 April 2026
  • 18 new database providers — now supporting 55+ database types
  • Cloud-native: DynamoDB, Cosmos DB, BigQuery, Redshift, Aurora
  • Enterprise: IBM Db2, SAP HANA
  • Graph: ArangoDB (K8s CRD discovery), Dgraph
  • Analytics: Apache Druid (CRD), Apache Pinot
  • Messaging: Apache Pulsar, NATS (CRD discovery)
  • Emerging: SurrealDB, CrateDB, QuestDB, FerretDB, HBase
  • Full monitoring, query insights, and performance advisors for all 18 types

Databases

dynamodbcosmosdbbigqueryredshiftauroradb2saphanaarangodbdgraphdruidpinotpulsarnatssurrealdbcratedbquestdbferretdbhbase
v1.2.0 April 2026
  • Live real-time charts for all database types with auto-refresh
  • Comprehensive Query Insights: CockroachDB, InfluxDB, Vector DBs, Elasticsearch, MongoDB, Cassandra/ScyllaDB
  • Full Performance Advisors: CockroachDB, InfluxDB, Memcached, Vector DBs
  • Enhanced MySQL, ClickHouse, Cassandra, RabbitMQ advisors with deep metrics
v1.1.0 April 2026
  • Deep database-specific monitoring for all supported types
  • MySQL/MariaDB: InnoDB buffer pool, QPS, slow queries, lock waits, advisor
  • ClickHouse: queries, merges, parts, memory, query log analysis
  • Cassandra/ScyllaDB: node ring, heap, thread pools, compaction, GC
  • RabbitMQ: queues, consumers, memory, disk, exchange details
  • Vector DBs: health, schema, collections, modules
  • Real-time charts and performance advisors per database engine
v1.0.0 April 2026
  • Universal discovery — 55+ database types across 30+ K8s operators
  • Direct Connect for VMs, bare-metal, and cloud-managed databases
  • 2-step environment registration with kubeconfig auto-detection
  • Real-time monitoring, query insights, and performance analysis
  • Automated backups with retention and one-click restore
  • Database browser, RBAC, multi-org, audit logging
  • Cross-platform: macOS (Apple Silicon), Windows, Linux

Databases

MongoDBPostgreSQLMySQLMariaDBSQL ServerCockroachDBYugabyteDBTiDBRedisValkeyMemcachedKafkaRabbitMQElasticsearchOpenSearchCassandraScyllaDBCouchbaseNeo4jClickHouseStarRocksTimescaleDBInfluxDBDuckDBMilvusWeaviateQdrantChromaDBetcdMinIONeonPlanetScaleSupabaseAiven