From 8e872f7778bef225df85e6bfa75f9ef0138cbe3c Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Mon, 8 Jun 2026 00:25:29 +1200 Subject: [PATCH 1/2] feat(client): optional TLS for the MongoDB connection Add a `$tls` constructor flag (default false, BC-preserving) that opens the Swoole socket with SWOOLE_SSL and enables encryption. Peer verification is disabled (ssl_verify_peer=false, ssl_allow_self_signed=true) because the backend is reached through a TLS-terminating proxy whose hostname is not on the backend's own certificate. Self-hosted plaintext connections are unaffected. Needed so Appwrite Cloud can reach a dedicated MongoDB backend (documentsdb) through the edge TCP proxy, which mandates TLS. Co-Authored-By: Claude Opus 4.8 --- src/Client.php | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/Client.php b/src/Client.php index 9d7884f..4f30eaa 100644 --- a/src/Client.php +++ b/src/Client.php @@ -142,7 +142,8 @@ public function __construct( int $port, string $user, string $password, - bool $useCoroutine = false + bool $useCoroutine = false, + bool $tls = false ) { if (empty($database)) { throw new \InvalidArgumentException('Database name cannot be empty'); @@ -177,18 +178,33 @@ public function __construct( } } + $flags = SWOOLE_SOCK_TCP | SWOOLE_KEEP; + if ($tls) { + $flags |= SWOOLE_SSL; + } + $this->client = $useCoroutine - ? new CoroutineClient(SWOOLE_SOCK_TCP | SWOOLE_KEEP) - : new SwooleClient(SWOOLE_SOCK_TCP | SWOOLE_KEEP); + ? new CoroutineClient($flags) + : new SwooleClient($flags); // Set socket options to prevent hanging - $this->client->set([ + $options = [ 'open_tcp_keepalive' => true, 'tcp_keepidle' => 4, // Start keepalive after 4s idle 'tcp_keepinterval' => 3, // Keepalive interval 3s 'tcp_keepcount' => 2, // Close after 2 failed keepalives 'timeout' => 30 // 30 second connection timeout - ]); + ]; + + if ($tls) { + // The backend is reached through a TLS-terminating proxy presenting a + // trusted platform certificate; encrypt the hop without enforcing peer + // verification (the proxy hostname is not on the backend's own cert). + $options['ssl_verify_peer'] = false; + $options['ssl_allow_self_signed'] = true; + } + + $this->client->set($options); $this->auth = new Auth([ 'authcid' => $user, From 1fc279eb27a53cd0611d19ff41206a0bd37d638e Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Mon, 8 Jun 2026 00:33:23 +1200 Subject: [PATCH 2/2] refactor(client): let caller own TLS verification policy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the hardcoded ssl_verify_peer=false with a $tlsOptions array merged into the socket options when TLS is enabled. The driver provides the TLS mechanism; the consumer decides verification — verify against the system CA in production, or relax it where the endpoint presents an untrusted certificate (e.g. a staging Let's Encrypt staging cert). Avoids baking a verification downgrade into the driver for all environments. Co-Authored-By: Claude Opus 4.8 --- src/Client.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Client.php b/src/Client.php index 4f30eaa..d54e9a6 100644 --- a/src/Client.php +++ b/src/Client.php @@ -143,7 +143,8 @@ public function __construct( string $user, string $password, bool $useCoroutine = false, - bool $tls = false + bool $tls = false, + array $tlsOptions = [] ) { if (empty($database)) { throw new \InvalidArgumentException('Database name cannot be empty'); @@ -197,11 +198,12 @@ public function __construct( ]; if ($tls) { - // The backend is reached through a TLS-terminating proxy presenting a - // trusted platform certificate; encrypt the hop without enforcing peer - // verification (the proxy hostname is not on the backend's own cert). - $options['ssl_verify_peer'] = false; - $options['ssl_allow_self_signed'] = true; + // TLS is the mechanism; the caller owns the verification policy. Pass + // ssl_verify_peer / ssl_cafile / ssl_host_name (etc.) via $tlsOptions — + // e.g. verify against the system CA in production, or relax verification + // where the endpoint presents an untrusted certificate. Defaults to + // Swoole's behaviour when no options are given. + $options = array_merge($options, $tlsOptions); } $this->client->set($options);