Mongo Studio UX: shared module chrome (context bar, headers, empty/loading states); double-click opens find template without auto-run; COLLSCAN confirm only on explicit Run
Mongo Studio perf: K8s find path skips inline explain + estimatedDocumentCount (fixes multi-minute hangs on large collections like stress_warm); session tree cache; listCollections nameOnly
Safe Ops: index add/drop removed from command surface (Indexes tab owns DDL); Operations Audit panel removed — history lives in Admin → Audit Log
Explorer guards: system.* blocks show correct toast (not write-blocked); bounded .limit finds skip redundant COLLSCAN preflight on warn/allow
GCP lab: zero-cost cleanup fixes shell quoting + includes verify-mongo-tls; maintenance/studio live verifiers expanded
v1.78.0 July 2026
Mongo maintenance: shared oplog resize validation + disk preflight for PSMDB and K8s-managed (990 MB floor, 80% disk cap, kubectl df probes)
Mongo maintenance: Right-Size Resources engine for K8s Community, StatefulSet, and PSMDB — preflight, CR patch, operator roll wait; rejects bare memory like "2" (must be 2Gi)
Mongo maintenance: rolling-restart poll logs surface real K8s API errors instead of generic "waiting for pod" lines
Mongo monitoring: per-member snapshot mappers, improved kubectl-exec primary routing, and Direct Connect member metrics hardening
Electron start script: unset ELECTRON_RUN_AS_NODE so the desktop shell boots the backend correctly from npm start
v1.77.4 July 2026
Mongo monitoring security: invalid ?member= on realtime/query-insights no longer falls back to stale cluster-wide cache — unknown members return 400
Direct Connect Diagnose: live Mongo snapshot capture during incident analysis when background jobs are off (TLS-only targets get sparse+ evidence without SSH logs)
GCP provision: reconcile TCP Direct Connect host on PUT; jump-stack VMs before IP read
v1.77.3 July 2026
Direct Connect Mongo (password auth): Studio browse authenticates against admin while commands run on the selected database; connect-time fallback retries authSource on the operational DB when admin auth fails (app-scoped users)
Direct Connect SSH probe: ssh_probe_host column, live SSH handshake in monitoring readiness, bastion-to-DB-host hop for host metrics/OS config/logs, SSH port validation, and Edit-modal connection string + CA PEM fields
Direct Connect Mongo (connection-string): fix Studio collection browse when credentials authenticate against admin but user databases differ — URI path now stays on the auth database while commands run on the selected DB
Direct Connect: auto-focus Connection Name after opening the add modal or selecting MongoDB (self-hosted); fixes Electron focus trap where the field was not clickable until reopen
Studio: collection-load toasts now surface the backend error message (auth / permissions) instead of a generic failure string
v1.77.0 June 2026
Mongo free-tier security: cross-org 404 on Studio/Monitoring/Advisor; aggregate/explain $out/$merge blocks on all Studio transports; K8s member/pod allowlists; advisor history cluster binding; Studio rate limit (60/min); audit-log org gate
Dead code removed: duplicate `codeAdvisorNarrative.ts`, unused single-query advisor wrappers, `emptyDirectGrowthHistory()`, stale `FTDC_LIMITATION_NOTE`
Docs: self-hosted per-flavor Mongo connect table on the marketing site; Atlas/vendor DBaaS explicitly out of GTM scope
Deferred to v1.78+: live incident drills (§1c), scale/concurrency tests, formal security pen-test sign-off, paywall click-through QA
v1.76.0 June 2026
Mongo Studio: K8s Community read-secondary routing — replica roles probed via replSetGetStatus on all pods, with ordinal fallback when roles are unknown
Incident Playbooks: PG/MySQL pod resolution via resolvePodAndContainer, MySQL performance_schema steps, primary-vs-replica detection, Cockroach-safe guards, History drill-down to past reports, and Run vs Severity columns (critical findings no longer show as failed runs)
Mongo monitoring: K8s pod CPU/memory as % of limit on realtime charts, opcounters Long coercion on kubectl-exec path, PRIMARY default member picker, and fresher realtime cache
Mongo Community provisioning: preflight/RBAC hardening and operator install improvements
v1.74.0 June 2026
Performance: app no longer stalls when a Kubernetes environment is unreachable — monitoring and health pages fail fast instead of waiting out API timeouts
Performance: faster cold start — the code editor (Monaco) and chart libraries now load on demand, shrinking the initial bundle by ~3.5MB
Performance: parallelized MongoDB credential discovery and added timeouts to slow Kubernetes calls
v1.73.0 June 2026
Tiering update: AI Diagnose (Incident RCA, Virtual DBA, auto-RCA alerts, Transaction Tracer), on-demand Health Check, and the BYO-AI assistant are now part of DBHelm Platform — connect, query/Studio, monitoring and the Advisor/Optimize suite stay free forever
Platform gates wired end-to-end: backend entitlement checks on diagnose, health-check and AI-generate, plus frontend route guards, sidebar locks and upgrade prompts
Marketing site synced with shipped features: Virtual DBA, AI Incident RCA & Diagnose and Live Migration (ClusterSync) feature cards, Schema Changes + Security Posture (DSPM) added, and refreshed pricing/FAQ tiers
v1.72.0 June 2026
Live Migration (ClusterSync): namespace-filtered live MongoDB cluster-to-cluster sync with initial copy, change-stream replication and guided cutover (Percona PCSM engine)
Virtual DBA: index advisor, table profiling, error explainer, migration safety review, and a draft-change handoff into Schema Changes
Virtual DBA: fleet/multi-DB mode, per-database policy with PII redaction, and a proactive daily health digest
Virtual DBA database picker now uses the Org/Env/Type/Instance hierarchy, matching Monitoring and Studio
Refreshed design docs (Architecture, HLD, Guide, Security Review) with all recent features
v1.71.0 June 2026
New Virtual DBA: a read-only conversational AI database administrator scoped to one database — answers questions grounded in the live DB via tools (overview, schema/indexes, live activity, slow queries, metrics, RCA, query optimization, read-only queries) with deep links into full RCA
Virtual DBA knowledge base: feed runbooks, conventions, and per-DB instructions, with semantic search when an embedding provider is configured (keyword fallback otherwise)
Virtual DBA now ships with built-in DBHelm product knowledge so it can also answer how-to / "where is X" questions about every module
Unified diagnostic alerts: when a metric rule fires it can auto-run Incident RCA scoped to the exact breaching pod and include the root cause + a "View RCA" deep link in the notification
Schema Changes: AI-assisted migration review — production-readiness verdict, ranked risks, rollout plan, and a safer SQL rewrite
New Security Posture module: CIS-style hardening scorecard for Postgres/MySQL with grade, remediation, scan history, and audit
v1.69.0 June 2026
Incident Playbooks: new High Memory, Cache Hit Ratio, and Index Health templates, plus a Composer to build your own playbooks from the UI
Declarative GitOps now does true drift correction: in-place cluster/object updates and prune-based deletes
Sidebar: Logs and Playbooks moved under Diagnose; Transaction Tracer retired
v1.68.0 June 2026
Incident RCA now collects authenticated MongoDB signals on Kubernetes (FTDC, currentOp, serverStatus, replSetGetStatus) using existing deployment secrets
Engine signals fall back to the legacy mongo shell on MongoDB 4.x images
Robust deep-signal pod/container selection fixes 'container not found' on non-standard Helm charts
New evidence-only (no-AI) RCA mode with rule-based heuristic findings
Direct Connect incident RCA, streaming progress, historical FTDC, baseline/change/plan signals, secret redaction, RCA history + follow-up Q&A
v1.67.0 June 2026
MongoDB Studio: insert & delete documents directly in the Explorer via Safe Ops
Safe Ops: one-click rollback for UPDATE/DELETE on Direct Connect & Kubernetes MongoDB
Monitoring: per-shard chunk distribution and sharding health recommendations
Monitoring: per-member historical charts for Direct Connect replica sets
Advisor: read-only diagnostic commands in IntelliShell, plan-cache insights, and version/FCV end-of-life checks
Fixed: PSMDB metrics now feed the embedded time-series store and alerts
Fixed: bulk multi-document import for Direct Connect and Kubernetes
v1.66.2 June 2026
Fixed a phantom "Direct Snapshot (internal)" environment that appeared with a health-check error for anyone using Direct Connections — the internal placeholder is no longer shown or health-checked
Hardened credential decryption to fail with a clear message instead of a cryptic Buffer error
v1.66.1 June 2026
Direct Connect: fixed "Connection to private/internal addresses is not allowed" — on-prem and LAN databases (private IPs like 10.x / 192.168.x / 172.16–31.x) now connect normally in the desktop app
v1.66.0 June 2026
Direct-Connect Redis across Studio, Monitoring, and Advisor
Embedded time-series monitoring now covers direct Cassandra and Redis
Performance Advisor for direct PostgreSQL and MySQL connections
Kafka advisor (broker & topic recommendations) and a unified SQL performance summary
Inline document editing in the MongoDB Explorer with guided diff + Safe Ops save
Metric alerts now supported for PostgreSQL, MySQL, Redis, and Cassandra
v1.65.1 June 2026
Fixed a CI preflight test failure that prevented release builds (including the macOS .dmg) from publishing
v1.65.0 June 2026
Embedded time-series monitoring (metrics.db) with history charts and a generic alerting engine — no Prometheus required
Provisioning: data-driven engine version catalog plus declarative CR and native-workload provider factories
Day-2 operations router — scale, version upgrade, volume expand, restart — for provisioned clusters
New ClickHouse provisioner; Redis/Kafka/ClickHouse/Cassandra provisions now appear in the fleet
Upgrade Rehearsal: auto-provision a fresh disposable target and auto-clone source into it
Diagnose: Cassandra engine signals and log collection
v1.64.0 June 2026
Upgrade Rehearsal: validate version upgrades on a disposable clone using real production traffic before touching prod
Supported across MongoDB, PostgreSQL, MySQL, and Cloud SQL with real-literal capture and replay
SQL write replay runs inside an always-rolled-back transaction — the clone is never mutated
Trustworthy verdicts: warm-up pass, multi-trial runs with a noise band, locked replay params, and clone-equivalence checks
Operational safety: cancellable capture/replay and crash-safe restore of orphaned MongoDB profiling
v1.63.22 June 2026
Cloud SQL Day-2 maintenance for any GCP instance — discovered or direct-connected
Admin-API ops (Instance Health, On-demand Backup, List Backups, Restart, HA Failover) plus SQL maintenance over Direct Connect
Capability-gated op catalog — each instance shows exactly what it can run, with reasons for the rest
Typed confirmation (retype the database name) for all destructive maintenance operations
v1.63.21 June 2026
Cassandra advisor: nodetool-driven findings with a CQL-only fallback for SSH-less direct connections
VM host metrics over SSH (load, disk, memory, disk I/O) for direct-connect Postgres, MySQL & Cassandra
Studio: SQL/CQL console result paging and one-click UPDATE/INSERT/DELETE generation from the row inspector
Mongo node-router (read-from-secondary) now available across all flavors including Direct Connect
Advisor: Optimize hub landing page for SQL engines and engine-aware Right-Sizing links
v1.63.20 June 2026
Cloud SQL (Postgres/MySQL): full free-tier support over Direct Connect — Dashboard, Realtime, Query Insights, Objects browser, and Transaction Tracer now run wire-native over TCP
Discovered Cloud SQL: live CPU/memory/disk/connections + read-replica lag and a disk-growth trend via GCP Cloud Monitoring (no DB connection required)
One-click "Connect over TCP" turns a discovered Cloud SQL instance into a full-tier Direct Connection
MySQL Objects: per-index size; Query Insights now shows the sampling window; direct connections show a TLS/SSL posture banner
v1.63.19 June 2026
MongoDB Direct Connect: use SSH for OS/log probing alongside a SOCKS5 transport (full replica-set coverage)
MongoDB Direct Connect: SOCKS5 now powers health checks and per-member views (Node Compare, per-member metrics, Query Insights picker)
MongoDB Direct Connect: SSH-tunnel per-member targeting forwards to the specific member
v1.63.18 June 2026
MongoDB Studio: read-from-secondary routing for community, statefulset & direct-connect
Query Insights: per-member picker across all MongoDB flavors
System Config: OS recommendations now target the actual data-volume device
Security: online TLS certificate rotation and credential rotation
v1.63.15 June 2026
MongoDB direct-connect (Atlas / self-managed): OS recommendations from mongod startup warnings, Slow-log Advisor + Index Suggestions sourced from system.profile, and process memory on the dashboard — all with no SSH
MongoDB free-tier: Query, Slow-log & Code advisors verified live on Kubernetes Community and StatefulSet MongoDB
Diagnostics: background jobs can be fully disabled (DBHAPP_DISABLE_JOBS) for safe headless/verification runs
v1.63.13 June 2026
MongoDB free tier: OS-level System Config recommendations now work on Kubernetes-managed MongoDB (Community + StatefulSet), collected via kubectl-exec — no SSH required.
MongoDB free tier: background metrics, performance, and extended snapshots now collect for Kubernetes-managed MongoDB, so dashboards and Index Suggestions build proper history.
Studio: collection-scan (COLLSCAN) hints now fire across every MongoDB flavor — fixed a payload mismatch that had silently disabled them on non-PSMDB clusters.
MongoDB dashboards: per-pod CPU/memory and per-member realtime metrics now populate for Kubernetes-managed MongoDB, matching the PSMDB experience.
Dashboard & All Databases refresh now actively re-probes environments whose databases were marked unreachable, so a recovered cluster self-heals instead of showing a stale status.
Plan Watch is now consistently shown as a free Optimize tool across the app and website.
v1.63.12 June 2026
Kubernetes environment error state now shows the exact root cause on Environments cards (timeout, auth failure, DNS, TLS, etc.) plus expandable "How to fix" steps — including gcloud/aws kubeconfig refresh commands when GCP/EKS metadata is known
All Databases cards and instance detail inherit the parent environment error when a cluster is unreachable, so operators see why status is stale without opening Logs or guessing from a red badge alone
Stale fleet reconcile: when a registered K8s environment goes offline, managed databases, provisioned clusters, and PSMDB rows flip to unreachable automatically on health check, refresh, and hierarchy load
Provision wizard: Configure step seeds default namespace (fixes "Namespace required" preflight when user accepts the placeholder), Mongo LoadBalancer endpoint resolves on poll, and provisioned-cluster Created date no longer shows Invalid Date
v1.63.11 June 2026
MongoDB Community provisioning hardened: wizard templates map bare "7.0" to a full patch version (7.0.19), preflight checks operator pod readiness + PVC quota + memory, and the detail page shows live rollout progress (CR / PVC / StatefulSet / pods) with auto-refresh
New Sync credentials action on provisioned Mongo clusters — pulls the live admin password from the K8s Secret into DBHelm after kubectl redeploys so Monitoring, Health Check, and Studio authenticate without manual re-entry
K8s Mongo monitoring panels (Lock Debug, Health Check, Replication Health) no longer crash on BSON Long objects from kubectl-exec JSON — values normalize before React render
Mongo Health Check deep probes use resolveMongoK8sCreds so Community Operator clusters ({cluster}-admin-password) work alongside PSMDB and StatefulSet secret conventions
v1.63.10 June 2026
Performance Advisor no longer hangs on 24h/7d windows on remote GKE — superseded scans are cancelled, backend serializes one live scan per database, and the UI keeps showing the previous window while the longer scan runs
Advisor module sub-tabs (Query, Slow Log, Code, Right-Sizing, Cost) render immediately instead of waiting for the slow Performance Advisor overview scan; K8s-managed Mongo is no longer misclassified as Direct Connect for Right-Sizing/Cost
K8s Mongo monitoring loads faster: dashboard and per-member metrics batch serverStatus/replSetGetStatus/hostInfo into one mongosh exec per pod, metric snapshot FK placeholders prevent collector failures, and Pro-tier Prometheus/GMP history falls back to local SQLite when credentials are missing
Added observability triage banner links (GCP/AWS console) and opt-in MetricsDebug logging for dashboard/member-metrics/performance load tracing
v1.63.9 June 2026
MongoDB monitoring and advisor panels (Query Advisor, Slow-log Advisor, Index Suggestions, Code Advisor, System Config) now show an actionable next step when a check fails — e.g. how to enable profiling, grant $indexStats privileges, or reach a cold cluster — instead of a raw error string
Free-tier MongoDB hardening verified live against real Percona (PSMDB) and Kubernetes-managed MongoDB clusters: dashboards, replication health, query insights, index suggestions, system-config recommendations, all advisors, and Studio query execution (find/aggregate/explain) were exercised end-to-end read-only
Added a "MongoDB free-tier limitations" support document covering supported flavors and transports, the profiler requirement for Query Insights, $indexStats privileges, OS-level system-config recommendations, advisor boundaries, realtime cold-start behavior, and a broken-connection runbook
Patched dependency vulnerabilities (npm audit) and added orchestration ("glue") tests for the live advisor runners and the Direct-Connect system-config assembly to lock in behavior
v1.63.8 June 2026
Renamed "Console" to "Studio" across the app for one consistent name — the navigation entry, page header, and "Open" buttons now all say Studio, with IntelliShell kept as the name of the smart editor inside
Studio panels are now resizable: drag the divider to widen the database tree or to rebalance the editor vs. results split, and your layout is remembered between sessions
Fixed a crash when opening Query Insights on log-derived data ("Cannot read properties of undefined") — the slow-query shape now always carries the fields the UI expects, and the scan-ratio cell degrades to "COLLSCAN" when unknown
Fixed Studio getting stuck on "Select an environment and cluster to begin" when opening a Percona (PSMDB) cluster on the free tier — the cluster is now pre-selected and the redundant picker is hidden
Save Active Query now works in the desktop app: the browser prompt (unsupported in Electron) was replaced with an inline naming field
Saved Queries and Execution History are now a single right-docked panel with richer history (impact, stopped state, formatted duration) instead of two separate left panels
Stop button now reliably cancels long find() queries, including paginated reads; rapid Next/Prev paging no longer races or overwrites newer results
Realtime metrics no longer error out on a cold PSMDB cluster — longer first-hit budget plus a "Warming up…" state instead of a hard failure
Replaced the native rollback confirmation with a styled in-app dialog that shows the exact command before you run it
v1.63.7 June 2026
Index Suggestions for Percona (PSMDB) MongoDB clusters now actually read the slow-query filter and sort from the log — previously they were never parsed, so the advisor returned no index recommendations even for obvious collection scans
System Config advisor no longer flags a low WiredTiger cache-hit ratio during warm-up: freshly provisioned clusters (uptime under an hour) have a cold cache, so the check now only runs once the ratio is meaningful
Hardened the recommendation engine against false positives: equality/range index fields are treated as direction-agnostic (no redundant index suggestions), keyFile/mechanism-secured clusters are no longer reported as "auth disabled", and findOne() is no longer flagged as an unbounded query
De-duplicated the System Config recommendation logic so the in-cluster and Direct Connect paths share one source of truth and can no longer drift
v1.63.6 June 2026
MongoDB Community Operator install now applies the CRD and RBAC (not just the operator Deployment) — fixes "CRD still isn't visible" install failures for the k8s-mongo-community provisioner
StatefulSet MongoDB clusters no longer get stuck in "Creating": readiness now recognizes a healthy replica set whether the primary is on pod-0 or any other member
Fixed StatefulSet pod-count flapping (3/3 → 2/3 on refresh) by giving the mongosh readiness probe a real timeout and tolerating brief election/initial-sync blips
v1.63.5 June 2026
Fixed MongoDB metrics showing 'partially unavailable' on clusters where mongosh prints a direct-connection notice — serverStatus/collStats now parse reliably, clearing false incident-mode/stale data
v1.63.4 June 2026
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
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
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.
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 — 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 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/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
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
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
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
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
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
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)
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
+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
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
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)
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
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
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
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
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