diff --git a/airbyte-cdk/java/airbyte-cdk/README.md b/airbyte-cdk/java/airbyte-cdk/README.md
index d5a77c1cd5419..ba258aeec234b 100644
--- a/airbyte-cdk/java/airbyte-cdk/README.md
+++ b/airbyte-cdk/java/airbyte-cdk/README.md
@@ -174,6 +174,7 @@ corresponds to that version.
 
 | Version    | Date       | Pull Request                                                | Subject                                                                                                                                                        |
 |:-----------|:-----------|:------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| 0.47.0     | 2024-09-26 | [\#42030](https://github.com/airbytehq/airbyte/pull/42030)  | minor refactor                                                                                                                                                 |
 | 0.46.1     | 2024-09-20 | [\#45700](https://github.com/airbytehq/airbyte/pull/45700)  | Destinations: Fix bug in parsing jsonschema |
 | 0.46.0     | 2024-09-18 | [\#45432](https://github.com/airbytehq/airbyte/pull/45432)  | upgrade all libraries to latest version |
 | 0.45.1     | 2024-09-17 | [\#45638](https://github.com/airbytehq/airbyte/pull/45638)  | upgrade apache mina sshd to 2.13.2 to handle openssh tcpkeepalive requests |
diff --git a/airbyte-cdk/java/airbyte-cdk/db-sources/src/main/kotlin/io/airbyte/cdk/integrations/source/jdbc/JdbcSSLConnectionUtils.kt b/airbyte-cdk/java/airbyte-cdk/core/src/main/kotlin/io/airbyte/cdk/db/jdbc/JdbcSSLConnectionUtils.kt
similarity index 96%
rename from airbyte-cdk/java/airbyte-cdk/db-sources/src/main/kotlin/io/airbyte/cdk/integrations/source/jdbc/JdbcSSLConnectionUtils.kt
rename to airbyte-cdk/java/airbyte-cdk/core/src/main/kotlin/io/airbyte/cdk/db/jdbc/JdbcSSLConnectionUtils.kt
index 2a300aef1049a..11217aa1d23e3 100644
--- a/airbyte-cdk/java/airbyte-cdk/db-sources/src/main/kotlin/io/airbyte/cdk/integrations/source/jdbc/JdbcSSLConnectionUtils.kt
+++ b/airbyte-cdk/java/airbyte-cdk/core/src/main/kotlin/io/airbyte/cdk/db/jdbc/JdbcSSLConnectionUtils.kt
@@ -1,12 +1,11 @@
 /*
- * Copyright (c) 2023 Airbyte, Inc., all rights reserved.
+ * Copyright (c) 2024 Airbyte, Inc., all rights reserved.
  */
-package io.airbyte.cdk.integrations.source.jdbc
+
+package io.airbyte.cdk.db.jdbc
 
 import com.fasterxml.jackson.databind.JsonNode
-import io.airbyte.cdk.db.jdbc.JdbcUtils
-import io.airbyte.cdk.db.util.SSLCertificateUtils.keyStoreFromCertificate
-import io.airbyte.cdk.db.util.SSLCertificateUtils.keyStoreFromClientCertificate
+import io.airbyte.cdk.db.util.SSLCertificateUtils
 import io.github.oshai.kotlinlogging.KotlinLogging
 import java.io.IOException
 import java.net.MalformedURLException
@@ -153,7 +152,7 @@ class JdbcSSLConnectionUtils {
                         val clientKeyPassword = getOrGeneratePassword(encryption)
                         try {
                             val caCertKeyStoreUri =
-                                keyStoreFromCertificate(
+                                SSLCertificateUtils.keyStoreFromCertificate(
                                     encryption[PARAM_CA_CERTIFICATE].asText(),
                                     clientKeyPassword,
                                     null,
@@ -214,7 +213,7 @@ class JdbcSSLConnectionUtils {
                         val clientKeyPassword = getOrGeneratePassword(encryption)
                         try {
                             val clientCertKeyStoreUri =
-                                keyStoreFromClientCertificate(
+                                SSLCertificateUtils.keyStoreFromClientCertificate(
                                     encryption[PARAM_CLIENT_CERTIFICATE].asText(),
                                     encryption[PARAM_CLIENT_KEY].asText(),
                                     clientKeyPassword,
diff --git a/airbyte-cdk/java/airbyte-cdk/core/src/main/kotlin/io/airbyte/cdk/integrations/base/ssh/SshTunnel.kt b/airbyte-cdk/java/airbyte-cdk/core/src/main/kotlin/io/airbyte/cdk/integrations/base/ssh/SshTunnel.kt
index c6383ae6b5514..b7be43760a137 100644
--- a/airbyte-cdk/java/airbyte-cdk/core/src/main/kotlin/io/airbyte/cdk/integrations/base/ssh/SshTunnel.kt
+++ b/airbyte-cdk/java/airbyte-cdk/core/src/main/kotlin/io/airbyte/cdk/integrations/base/ssh/SshTunnel.kt
@@ -409,13 +409,14 @@ constructor(
         const val GLOBAL_HEARTBEAT_INTERVAL_DEFAULT_IN_MILLIS: Long = 2000
         const val IDLE_TIMEOUT_KEY: String = "idle_timeout"
         const val IDLE_TIMEOUT_DEFAULT_INFINITE: Long = 0
+        const val TUNNEL_METHOD_KEY = "tunnel_method"
 
         const val TIMEOUT_MILLIS: Int = 15000 // 15 seconds
 
         @JvmStatic
         fun getInstance(config: JsonNode, hostKey: List<String>, portKey: List<String>): SshTunnel {
             val tunnelMethod =
-                Jsons.getOptional(config, "tunnel_method", "tunnel_method")
+                Jsons.getOptional(config, TUNNEL_METHOD_KEY, TUNNEL_METHOD_KEY)
                     .map { method: JsonNode ->
                         TunnelMethod.valueOf(method.asText().trim { it <= ' ' })
                     }
@@ -429,12 +430,12 @@ constructor(
                 null,
                 null,
                 tunnelMethod,
-                Strings.safeTrim(Jsons.getStringOrNull(config, "tunnel_method", "tunnel_host")),
-                Jsons.getIntOrZero(config, "tunnel_method", "tunnel_port"),
-                Strings.safeTrim(Jsons.getStringOrNull(config, "tunnel_method", "tunnel_user")),
-                Strings.safeTrim(Jsons.getStringOrNull(config, "tunnel_method", "ssh_key")),
+                Strings.safeTrim(Jsons.getStringOrNull(config, TUNNEL_METHOD_KEY, "tunnel_host")),
+                Jsons.getIntOrZero(config, TUNNEL_METHOD_KEY, "tunnel_port"),
+                Strings.safeTrim(Jsons.getStringOrNull(config, TUNNEL_METHOD_KEY, "tunnel_user")),
+                Strings.safeTrim(Jsons.getStringOrNull(config, TUNNEL_METHOD_KEY, "ssh_key")),
                 Strings.safeTrim(
-                    Jsons.getStringOrNull(config, "tunnel_method", "tunnel_user_password")
+                    Jsons.getStringOrNull(config, TUNNEL_METHOD_KEY, "tunnel_user_password")
                 ),
                 Strings.safeTrim(Jsons.getStringOrNull(config, hostKey)),
                 Jsons.getIntOrZero(config, portKey),
@@ -479,7 +480,7 @@ constructor(
         @Throws(Exception::class)
         fun getInstance(config: JsonNode, endPointKey: String): SshTunnel {
             val tunnelMethod =
-                Jsons.getOptional(config, "tunnel_method", "tunnel_method")
+                Jsons.getOptional(config, TUNNEL_METHOD_KEY, TUNNEL_METHOD_KEY)
                     .map { method: JsonNode ->
                         TunnelMethod.valueOf(method.asText().trim { it <= ' ' })
                     }
@@ -493,12 +494,12 @@ constructor(
                 endPointKey,
                 Jsons.getStringOrNull(config, endPointKey),
                 tunnelMethod,
-                Strings.safeTrim(Jsons.getStringOrNull(config, "tunnel_method", "tunnel_host")),
-                Jsons.getIntOrZero(config, "tunnel_method", "tunnel_port"),
-                Strings.safeTrim(Jsons.getStringOrNull(config, "tunnel_method", "tunnel_user")),
-                Strings.safeTrim(Jsons.getStringOrNull(config, "tunnel_method", "ssh_key")),
+                Strings.safeTrim(Jsons.getStringOrNull(config, TUNNEL_METHOD_KEY, "tunnel_host")),
+                Jsons.getIntOrZero(config, TUNNEL_METHOD_KEY, "tunnel_port"),
+                Strings.safeTrim(Jsons.getStringOrNull(config, TUNNEL_METHOD_KEY, "tunnel_user")),
+                Strings.safeTrim(Jsons.getStringOrNull(config, TUNNEL_METHOD_KEY, "ssh_key")),
                 Strings.safeTrim(
-                    Jsons.getStringOrNull(config, "tunnel_method", "tunnel_user_password")
+                    Jsons.getStringOrNull(config, TUNNEL_METHOD_KEY, "tunnel_user_password")
                 ),
                 null,
                 0,
diff --git a/airbyte-cdk/java/airbyte-cdk/core/src/main/resources/version.properties b/airbyte-cdk/java/airbyte-cdk/core/src/main/resources/version.properties
index 99d22a58cc9dc..42482588ea2e0 100644
--- a/airbyte-cdk/java/airbyte-cdk/core/src/main/resources/version.properties
+++ b/airbyte-cdk/java/airbyte-cdk/core/src/main/resources/version.properties
@@ -1 +1 @@
-version=0.46.1
+version=0.47.0
diff --git a/airbyte-cdk/java/airbyte-cdk/dependencies/src/main/kotlin/io/airbyte/commons/json/JsonSchemas.kt b/airbyte-cdk/java/airbyte-cdk/dependencies/src/main/kotlin/io/airbyte/commons/json/JsonSchemas.kt
index 219655e420d13..543d90fd6a7c1 100644
--- a/airbyte-cdk/java/airbyte-cdk/dependencies/src/main/kotlin/io/airbyte/commons/json/JsonSchemas.kt
+++ b/airbyte-cdk/java/airbyte-cdk/dependencies/src/main/kotlin/io/airbyte/commons/json/JsonSchemas.kt
@@ -24,7 +24,7 @@ private val log = KotlinLogging.logger {}
 object JsonSchemas {
     private const val JSON_SCHEMA_ENUM_KEY = "enum"
     private const val JSON_SCHEMA_TYPE_KEY = "type"
-    private const val JSON_SCHEMA_PROPERTIES_KEY = "properties"
+    const val JSON_SCHEMA_PROPERTIES_KEY = "properties"
     private const val JSON_SCHEMA_ITEMS_KEY = "items"
 
     // all JSONSchema types.