Repository: appwrite/appwrite
Pull request #9748: Feat/index length
Author: login: ArnabChatterjee20k
Created: 2025-05-13T05:07:35Z | Merged: 2025-05-14T01:24:19Z

<!--
Thank you for sending the PR! We appreciate you spending the time to work on these changes.

Help us understand your motivation by explaining why you decided to make this change.

You can learn more about contributing to appwrite here: https://github.com/appwrite/appwrite/blob/master/CONTRIBUTING.md

Happy contributing!

-->

Add a new lengths parameter to the createIndex route, and pass it through to the index that gets created by the Databases worker. It should allow an array of integers, and to be index matched against the attributes. E.g.

attributes: [title, name, releasedAt]

lengths: [255, 255, 255]

## Test Plan
Added test testGetIndexByKeyWithLengths for creating index with lengths and fetching them and comparing them 

## Related PRs and Issues

- (Related PR or issue)

## Checklist

- [x] Have you read the [Contributing Guidelines on issues](https://github.com/appwrite/appwrite/blob/master/CONTRIBUTING.md)?
- [x] If the PR includes a change to an API's metadata (desc, label, params, etc.), does it also include updated API specs and example docs?


<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

- **New Features**
  - Added support for Figma as a new OAuth2 provider.
  - Introduced new environment variables for enhanced configuration, including compression, domain restrictions, storage, maintenance, auditing, and statistics.
  - Expanded OpenAPI and client specifications with new endpoint grouping, batch document creation, and additional metadata.

- **Improvements**
  - Updated SDK versions and enhanced function runtime support (including new Deno and Node.js versions).
  - Refined error handling with new error codes and improved descriptions.
  - Enhanced localization with richer country and continent metadata and improved email template punctuation across many languages.
  - Updated documentation and contributing guides for clarity and new features.
  - Improved Docker image with updated base version and new dependencies.

- **Bug Fixes**
  - Corrected and clarified various API descriptions, examples, and endpoint behaviors.
  - Fixed typos and improved consistency in documentation and configuration.

- **Chores**
  - Updated workflow automation, caching, and action versions.
  - Simplified and updated regional configuration and platform role assignments.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php
index 0bdb42ec1c1..cac713948a4 100644
--- a/app/controllers/api/databases.php
+++ b/app/controllers/api/databases.php
@@ -2813,11 +2813,12 @@ function updateAttribute(
     ->param('type', null, new WhiteList([Database::INDEX_KEY, Database::INDEX_FULLTEXT, Database::INDEX_UNIQUE]), 'Index type.')
     ->param('attributes', null, new ArrayList(new Key(true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of attributes to index. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' attributes are allowed, each 32 characters long.')
     ->param('orders', [], new ArrayList(new WhiteList(['ASC', 'DESC'], false, Database::VAR_STRING), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of index orders. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' orders are allowed.', true)
+    ->param('lengths', [], new ArrayList(new Nullable(new Integer()), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Length of index. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE, optional:true)
     ->inject('response')
     ->inject('dbForProject')
     ->inject('queueForDatabase')
     ->inject('queueForEvents')
-    ->action(function (string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) {
+    ->action(function (string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, array $lengths, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) {
 
         $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
 
@@ -2877,9 +2878,6 @@ function updateAttribute(
             'size' => 0
         ];
 
-        // lengths hidden by default
-        $lengths = [];
-
         foreach ($attributes as $i => $attribute) {
             // find attribute metadata in collection document
             $attributeIndex = \array_search($attribute, array_column($oldAttributes, 'key'));
@@ -2901,8 +2899,7 @@ function updateAttribute(
                 throw new Exception(Exception::ATTRIBUTE_NOT_AVAILABLE, 'Attribute not available: ' . $oldAttributes[$attributeIndex]['key']);
             }
 
-            $lengths[$i] = null;
-
+            $lengths[$i] ??= null;
             if ($attributeArray === true) {
                 $lengths[$i] = Database::ARRAY_INDEX_LENGTH;
                 $orders[$i] = null;
diff --git a/composer.json b/composer.json
index 9e45f71c611..9b2cf7a1ab2 100644
--- a/composer.json
+++ b/composer.json
@@ -51,7 +51,7 @@
         "utopia-php/cache": "0.13.*",
         "utopia-php/cli": "0.15.*",
         "utopia-php/config": "0.2.*",
-        "utopia-php/database": "0.68.*",
+        "utopia-php/database": "0.69.*",
         "utopia-php/domains": "0.5.*",
         "utopia-php/dsn": "0.2.1",
         "utopia-php/framework": "0.33.*",
diff --git a/composer.lock b/composer.lock
index cf15b7657e5..e6bcd919e25 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "a5c4c6b723423bc6cb3a7344ab071b43",
+    "content-hash": "1eeb5a0f3560aefd8f71bd0955e30360",
     "packages": [
         {
             "name": "adhocore/jwt",
@@ -1109,16 +1109,16 @@
         },
         {
             "name": "open-telemetry/api",
-            "version": "1.2.3",
+            "version": "1.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/opentelemetry-php/api.git",
-                "reference": "199d7ddda88f5f5619fa73463f1a5a7149ccd1f1"
+                "reference": "4e3bb38e069876fb73c2ce85c89583bf2b28cd86"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/opentelemetry-php/api/zipball/199d7ddda88f5f5619fa73463f1a5a7149ccd1f1",
-                "reference": "199d7ddda88f5f5619fa73463f1a5a7149ccd1f1",
+                "url": "https://api.github.com/repos/opentelemetry-php/api/zipball/4e3bb38e069876fb73c2ce85c89583bf2b28cd86",
+                "reference": "4e3bb38e069876fb73c2ce85c89583bf2b28cd86",
                 "shasum": ""
             },
             "require": {
@@ -1175,7 +1175,7 @@
                 "issues": "https://github.com/open-telemetry/opentelemetry-php/issues",
                 "source": "https://github.com/open-telemetry/opentelemetry-php"
             },
-            "time": "2025-03-05T21:42:54+00:00"
+            "time": "2025-05-07T12:32:21+00:00"
         },
         {
             "name": "open-telemetry/context",
@@ -1238,16 +1238,16 @@
         },
         {
             "name": "open-telemetry/exporter-otlp",
-            "version": "1.2.1",
+            "version": "1.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/opentelemetry-php/exporter-otlp.git",
-                "reference": "b7580440b7481a98da97aceabeb46e1b276c8747"
+                "reference": "19adf03d2b0f91f9e9b1c7f93db6c755c737cf6c"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/b7580440b7481a98da97aceabeb46e1b276c8747",
-                "reference": "b7580440b7481a98da97aceabeb46e1b276c8747",
+                "url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/19adf03d2b0f91f9e9b1c7f93db6c755c737cf6c",
+                "reference": "19adf03d2b0f91f9e9b1c7f93db6c755c737cf6c",
                 "shasum": ""
             },
             "require": {
@@ -1298,7 +1298,7 @@
                 "issues": "https://github.com/open-telemetry/opentelemetry-php/issues",
                 "source": "https://github.com/open-telemetry/opentelemetry-php"
             },
-            "time": "2025-03-06T23:21:56+00:00"
+            "time": "2025-05-12T00:36:35+00:00"
         },
         {
             "name": "open-telemetry/gen-otlp-protobuf",
@@ -1365,16 +1365,16 @@
         },
         {
             "name": "open-telemetry/sdk",
-            "version": "1.3.0",
+            "version": "1.4.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/opentelemetry-php/sdk.git",
-                "reference": "05d9ceb6773b5bddcf485af6d4a6f543bbeb980b"
+                "reference": "939d3a28395c249a763676458140dad44b3a8011"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/05d9ceb6773b5bddcf485af6d4a6f543bbeb980b",
-                "reference": "05d9ceb6773b5bddcf485af6d4a6f543bbeb980b",
+                "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/939d3a28395c249a763676458140dad44b3a8011",
+                "reference": "939d3a28395c249a763676458140dad44b3a8011",
                 "shasum": ""
             },
             "require": {
@@ -1451,7 +1451,7 @@
                 "issues": "https://github.com/open-telemetry/opentelemetry-php/issues",
                 "source": "https://github.com/open-telemetry/opentelemetry-php"
             },
-            "time": "2025-05-01T23:20:43+00:00"
+            "time": "2025-05-07T12:32:21+00:00"
         },
         {
             "name": "open-telemetry/sem-conv",
@@ -3499,16 +3499,16 @@
         },
         {
             "name": "utopia-php/database",
-            "version": "0.68.1",
+            "version": "0.69.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/utopia-php/database.git",
-                "reference": "72b2e2c0b875028f7d9dd755f6d4524b693c6507"
+                "reference": "cc6538e05e25d930244ab938c966d32db0922e83"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/utopia-php/database/zipball/72b2e2c0b875028f7d9dd755f6d4524b693c6507",
-                "reference": "72b2e2c0b875028f7d9dd755f6d4524b693c6507",
+                "url": "https://api.github.com/repos/utopia-php/database/zipball/cc6538e05e25d930244ab938c966d32db0922e83",
+                "reference": "cc6538e05e25d930244ab938c966d32db0922e83",
                 "shasum": ""
             },
             "require": {
@@ -3549,9 +3549,9 @@
             ],
             "support": {
                 "issues": "https://github.com/utopia-php/database/issues",
-                "source": "https://github.com/utopia-php/database/tree/0.68.1"
+                "source": "https://github.com/utopia-php/database/tree/0.69.1"
             },
-            "time": "2025-05-09T10:08:53+00:00"
+            "time": "2025-05-13T12:00:31+00:00"
         },
         {
             "name": "utopia-php/domains",
diff --git a/src/Appwrite/Utopia/Response/Model/Index.php b/src/Appwrite/Utopia/Response/Model/Index.php
index 2d795ad4396..fcd978b5bed 100644
--- a/src/Appwrite/Utopia/Response/Model/Index.php
+++ b/src/Appwrite/Utopia/Response/Model/Index.php
@@ -41,6 +41,13 @@ public function __construct()
                 'example' => [],
                 'array' => true,
             ])
+            ->addRule('lengths', [
+                'type' => self::TYPE_INTEGER,
+                'description' => 'Index attributes length.',
+                'default' => [],
+                'example' => [],
+                'array' => true,
+            ])
             ->addRule('orders', [
                 'type' => self::TYPE_STRING,
                 'description' => 'Index orders.',
diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php
index 1f19c514d10..2b60dee856b 100644
--- a/tests/e2e/Services/Databases/DatabasesBase.php
+++ b/tests/e2e/Services/Databases/DatabasesBase.php
@@ -1422,9 +1422,102 @@ public function testCreateIndexes(array $data): array
         return $data;
     }
 
+
     /**
-     * @depends testCreateIndexes
-     */
+ * @depends testCreateAttributes
+ */
+    public function testGetIndexByKeyWithLengths(array $data): void
+    {
+        $databaseId = $data['databaseId'];
+        $collectionId = $data['moviesId'];
+
+        // Test case for valid lengths
+        $create = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/indexes", [
+            'content-type' => 'application/json',
+            'x-appwrite-project' => $this->getProject()['$id'],
+            'x-appwrite-key' => $this->getProject()['apiKey']
+        ], [
+            'key' => 'lengthTestIndex',
+            'type' => 'key',
+            'attributes' => ['title','description'],
+            'lengths' => [128,200]
+        ]);
+        $this->assertEquals(202, $create['headers']['status-code']);
+
+        // Fetch index and check correct lengths
+        $index = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/indexes/lengthTestIndex", [
+            'content-type' => 'application/json',
+            'x-appwrite-project' => $this->getProject()['$id'],
+            'x-appwrite-key' => $this->getProject()['apiKey']
+        ]);
+        $this->assertEquals(200, $index['headers']['status-code']);
+        $this->assertEquals('lengthTestIndex', $index['body']['key']);
+        $this->assertEquals([128, 200], $index['body']['lengths']);
+
+        // Test case for lengths array overriding
+        // set a length for an array attribute, it should get overriden with Database::ARRAY_INDEX_LENGTH
+        $create = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/indexes", [
+            'content-type' => 'application/json',
+            'x-appwrite-project' => $this->getProject()['$id'],
+            'x-appwrite-key' => $this->getProject()['apiKey']
+        ], [
+            'key' => 'lengthOverrideTestIndex',
+            'type' => 'key',
+            'attributes' => ['actors'],
+            'lengths' => [120]
+        ]);
+        $this->assertEquals(202, $create['headers']['status-code']);
+
+        $index = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/indexes/lengthOverrideTestIndex", [
+            'content-type' => 'application/json',
+            'x-appwrite-project' => $this->getProject()['$id'],
+            'x-appwrite-key' => $this->getProject()['apiKey']
+        ]);
+        $this->assertEquals([Database::ARRAY_INDEX_LENGTH], $index['body']['lengths']);
+
+        // Test case for count of lengths greater than attributes (should throw 400)
+        $create = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/indexes", [
+            'content-type' => 'application/json',
+            'x-appwrite-project' => $this->getProject()['$id'],
+            'x-appwrite-key' => $this->getProject()['apiKey']
+        ], [
+            'key' => 'lengthCountExceededIndex',
+            'type' => 'key',
+            'attributes' => ['title'],
+            'lengths' => [128, 128]
+        ]);
+        $this->assertEquals(400, $create['headers']['status-code']);
+
+        // Test case for lengths exceeding total of 768
+        $create = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/indexes", [
+            'content-type' => 'application/json',
+            'x-appwrite-project' => $this->getProject()['$id'],
+            'x-appwrite-key' => $this->getProject()['apiKey']
+        ], [
+            'key' => 'lengthTooLargeIndex',
+            'type' => 'key',
+            'attributes' => ['title','description','tagline','actors'],
+            'lengths' => [256,256,256,20]
+        ]);
+
+        $this->assertEquals(400, $create['headers']['status-code']);
+
+        // Test case for negative length values
+        $create = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/indexes", [
+            'content-type' => 'application/json',
+            'x-appwrite-project' => $this->getProject()['$id'],
+            'x-appwrite-key' => $this->getProject()['apiKey']
+        ], [
+            'key' => 'negativeLengthIndex',
+            'type' => 'key',
+            'attributes' => ['title'],
+            'lengths' => [-1]
+        ]);
+        $this->assertEquals(400, $create['headers']['status-code']);
+    }
+    /**
+        * @depends testCreateIndexes
+        */
     public function testListIndexes(array $data): void
     {
         $databaseId = $data['databaseId'];


Reviews:
user: login: coderabbitai[bot]
body: > [!CAUTION]
> Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.  If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

**Actionable comments posted: 13**

<details>
<summary>🔭 Outside diff range comments (1)</summary><blockquote>

<details>
<summary>app/config/specs/open-api3-latest-client.json (1)</summary><blockquote>

`1-9714`: _⚠️ Potential issue_

**Missing `lengths` parameter for `createIndex`**  
The PR objectives describe adding a `lengths` array parameter to the `createIndex` route, but this spec file does not include that change. Please add the new `lengths` parameter under the `createIndex` path—both in the request schema and in the parameter list—so the client spec matches the implemented API.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Gitleaks (8.21.2)</summary>

8878-8878: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.

(jwt)

</details>
<details>
<summary>🪛 Checkov (3.2.334)</summary>

[HIGH] 1-9751: Ensure that the global security field has rules defined

(CKV_OPENAPI_4)

---

[MEDIUM] 291-296: Ensure that arrays have a maximum number of items

(CKV_OPENAPI_21)

</details>

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (22)</summary><blockquote>

<details>
<summary>app/config/locale/translations/kn.json (1)</summary><blockquote>

`248-248`: **Ensure trailing newline at EOF**  
Including a newline at end-of-file is best practice for POSIX compliance.

</blockquote></details>
<details>
<summary>app/config/locale/translations/vi.json (1)</summary><blockquote>

`248-248`: **Add newline at end-of-file**  
Ensure the file ends with a newline for POSIX compatibility.

</blockquote></details>
<details>
<summary>app/config/locale/translations/km.json (1)</summary><blockquote>

`248-248`: **Ensure newline at EOF**  
Add a trailing newline to comply with POSIX standards.

</blockquote></details>
<details>
<summary>app/config/locale/translations/ro.json (1)</summary><blockquote>

`248-248`: **Ensure trailing newline at EOF**  
Adding a newline at end-of-file helps maintain POSIX tool compatibility.

</blockquote></details>
<details>
<summary>app/config/locale/translations/eo.json (1)</summary><blockquote>

`9-9`: **Extra Period in Verification Sign-off**  
The updated “thanks” value is `"Dankegon.,"`, which introduces both a period and a comma. Consider removing the extra period for natural Esperanto punctuation, e.g., `"Dankegon,"`.

</blockquote></details>
<details>
<summary>app/config/locale/translations/zh-cn.json (2)</summary><blockquote>

`242-242`: **Unintended Newline in OTP Greeting**  
The OTP greeting includes a literal newline (`"\n"`) between punctuation marks: `"你好，\n、"`. This likely deviates from the intended format—consider removing the newline.

---

`246-246`: **Double Punctuation in OTP Sign-off**  
The OTP “thanks” string `"谢谢，、"` contains both a comma and the Chinese list comma. Please verify if both are required or remove the extra comma for clarity.

</blockquote></details>
<details>
<summary>app/config/collections/logs.php (1)</summary><blockquote>

`74-74`: **Consider documenting the expected format of the lengths array**

The array is correctly implemented but empty. For maintainability, consider adding a comment indicating the expected format (e.g., `// Expected format: [255, 255]`) to help future developers understand how to populate this array.

</blockquote></details>
<details>
<summary>app/config/console.php (1)</summary><blockquote>

`22-29`: **Consider adding support for multiple environments**

The platforms array only includes 'Localhost'. For a more robust configuration, consider supporting additional environments (development, staging, production) conditionally based on environment variables.

</blockquote></details>
<details>
<summary>CONTRIBUTING.md (1)</summary><blockquote>

`616-626`: **Fix grammar issues in the preview domains section.**

There are a few grammar issues in the new section:

```diff
-Appwrite Functions are automatically given a domain you can visit to execute the function. This domain has format `[SOMETHING].functions.localhost` unless you changed `_APP_DOMAIN_FUNCTIONS` environment variable. This default value works great when running Appwrite locally, but it can be impossible to use preview domains with Cloud woekspaces such as Gitpod or GitHub Codespaces.
+Appwrite Functions are automatically given a domain you can visit to execute the function. This domain has the format `[SOMETHING].functions.localhost` unless you've changed the `_APP_DOMAIN_FUNCTIONS` environment variable. This default value works great when running Appwrite locally, but it can be impossible to use preview domains with Cloud workspaces such as Gitpod or GitHub Codespaces.

-To use preview domains on Cloud workspaces, you can visit hostname provided by them, and supply function's preview domain as URL parameter:
+To use preview domains on Cloud workspaces, you can visit the hostname provided by them, and supply the function's preview domain as a URL parameter:

-The path was set to `/ping` intentionally. Visiting `/` for preview domains might trigger Console background worker, and trigger redirect to Console without our preview URL param. Visiting different path ensures this doesnt happen.
+The path was set to `/ping` intentionally. Visiting `/` for preview domains might trigger the Console background worker, and redirect to Console without our preview URL param. Visiting a different path ensures this doesn't happen.
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 LanguageTool</summary>

[grammar] ~618-~618: It appears that the past participle should be used here.
Context: ...o execute the function. This domain has format `[SOMETHING].functions.localhost` unles...

(HAVE_PART_AGREEMENT)

---

[uncategorized] ~620-~620: Possible missing article found.
Context: ...ains on Cloud workspaces, you can visit hostname provided by them, and supply function's...

(AI_HYDRA_LEO_MISSING_THE)

---

[uncategorized] ~620-~620: Possible missing article found.
Context: ...t hostname provided by them, and supply function's preview domain as URL parameter:  ```...

(AI_HYDRA_LEO_MISSING_THE)

</details>
<details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

622-622: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

</details>

</details>

</blockquote></details>
<details>
<summary>app/config/collections/common.php (2)</summary><blockquote>

`1666-1670`: **Class-name casing inconsistency (`DATABASE` vs `Database`)**

PHP class names are case-insensitive, so this won’t crash, but it does violate the project’s own style shown elsewhere in the file (`Database::METADATA`).  
Keeping a single casing avoids confusion and helps static analysis tools.

```diff
-        '$collection' => ID::custom(DATABASE::METADATA),
+        '$collection' => ID::custom(Database::METADATA),
```

(The same pattern repeats in `messages`, `topics`, `subscribers`, and `targets` blocks.)  
Consider running a quick search-replace to stay consistent.

---

`118-118`: **Minor typo in comment (`digitts`)**

```diff
- 16, // leading '+' and 15 digitts maximum by E.164 format
+ 16, // leading '+' and 15 digits maximum by E.164 format
```

</blockquote></details>
<details>
<summary>app/config/function-templates.php (1)</summary><blockquote>

`235-235`: **Typo in the tagline.**

There's a typo in MongoDB Atlas's tagline: "geospecial" should be "geospatial".

```diff
-            'Realtime NoSQL document database with geospecial, graph, search, and vector suport.',
+            'Realtime NoSQL document database with geospatial, graph, search, and vector support.',
```

</blockquote></details>
<details>
<summary>.github/workflows/tests.yml (1)</summary><blockquote>

`243-243`: **Remove trailing whitespace.**

There's a trailing whitespace at the end of line 243.

```diff
-          
+
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 243-243: trailing spaces

(trailing-spaces)

</details>

</details>

</blockquote></details>
<details>
<summary>app/config/collections/projects.php (1)</summary><blockquote>

`550-558`: **Small style nit – prefer the constant over magic number**  
`'lengths' => [64]` hard-codes the index prefix size, whereas elsewhere you rely on `Database::LENGTH_KEY` or attribute-size values.  Using the constant improves discoverability and prevents divergence if the canonical length ever changes.

```diff
-   'lengths' => [64],
+   'lengths' => [Database::LENGTH_KEY],
```

</blockquote></details>
<details>
<summary>app/cli.php (2)</summary><blockquote>

`127-139`: **`_APP_DATABASE_SHARED_TABLES` parsing duplicates & ignores whitespace**

The same explode/`in_array` logic is repeated twice and does not trim blanks, so  
`" hostA ,hostB"` won’t match. Centralise and normalise to avoid subtle bugs:

```diff
-$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
+// Normalise once
+$sharedTables = \array_filter(
+    \array_map('trim', \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')))
+);
```

Consider extracting this into a small helper to DRY the two blocks.  



Also applies to: 151-159

---

`173-177`: **`$database` is not captured by reference – cache may reset each call**

Inside `getLogsDB` the closure captures `$database` *by value*. Although the
variable persists within the closure instance, re-assigning it does **not**
update the outer scope when the closure is rebuilt (e.g. during DI reloads).

```diff
-return function (?Document $project = null) use ($pools, $cache, $database) {
+return function (?Document $project = null) use ($pools, $cache, &$database) {
```

Using `&$database` guarantees the single shared connection is reused as
intended.

</blockquote></details>
<details>
<summary>app/config/collections/platform.php (3)</summary><blockquote>

`224-234`: **Clarify and cap the `templates` column size before shipping**  
The hard-coded size `1000000` is flagged with a TODO. Storing 1 MB in a single `VARCHAR`/`TEXT` column can hurt index performance and may hit engine-specific limits (e.g. MySQL `VARCHAR` max 65 535 in UTF-8). Please verify the actual upper-bound required for template payloads and:

1. Use a dedicated constant instead of a magic number.  
2. Consider switching to `MEDIUMTEXT`/`LONGTEXT` if multi-KB bodies are truly needed; otherwise tighten the length to the realistic maximum.

---

`1645-1651`: **Empty `vcsCommentLocks` schema – intentional?**  
The collection is declared with no attributes or indexes. If this is a placeholder, add a comment explaining its future purpose; otherwise remove to avoid deploying dead tables.

---

`1-1652`: **Consider splitting gigantic schema into domain-specific files**  
At 1 600+ lines this single config file is hard to navigate, review, and merge-conflict-prone.  A common practice is one file per collection (or per bounded context) and an aggregator that `array_merge`s them.

This has no runtime cost but greatly improves maintainability.

</blockquote></details>
<details>
<summary>app/config/specs/open-api3-1.6.x-client.json (2)</summary><blockquote>

`21-24`: **Document the `<REGION>` placeholder in `servers`**  
Adding `https://<REGION>.cloud.appwrite.io/v1` is great. Consider expanding the description to explain valid `<REGION>` values, fallback behavior, and how clients should substitute it.

---

`3285-3287`: **Avoid using `null` for `group`**  
The `group` property is defined as a string in your metadata schema. Setting it to `null` may violate schema validation. If an endpoint doesn’t belong to a group, omit the `group` field altogether. 


Also applies to: 3412-3413, 3543-3545, 3601-3603, 4089-4091, 4172-4173, 4263-4265, 5261-5262, 5313-5314, 5365-5366, 5417-5418, 5469-5470, 5519-5520, 5573-5574, 5625-5626

</blockquote></details>

</blockquote></details>

<details>
<summary>🛑 Comments failed to post (13)</summary><blockquote>

<details>
<summary>app/config/locale/translations/sk.json (1)</summary><blockquote>

10-10: _⚠️ Potential issue_

**Fix misplaced period before comma**  
The verification thanks line is `"Ďakujeme.,"`, which combines a period and comma. It should be `"Ďakujeme,"` without the period.  

Apply this diff:
```diff
-  "emails.verification.thanks": "Ďakujeme.,",
+  "emails.verification.thanks": "Ďakujeme,",
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
    "emails.verification.thanks": "Ďakujeme,",
`````

</details>

<!-- suggestion_end -->

</blockquote></details>
<details>
<summary>app/config/locale/translations/tl.json (1)</summary><blockquote>

13-13: _⚠️ Potential issue_

**Remove extraneous space before comma**  
The greeting string `"Kamusta ,"` contains an extra space before the comma, which will render as `"Kamusta ,"` instead of `"Kamusta,"`.  

Apply this diff to correct it:
```diff
-"emails.magicSession.hello": "Kamusta ,",
+"emails.magicSession.hello": "Kamusta,",
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
    "emails.magicSession.hello": "Kamusta,",
`````

</details>

<!-- suggestion_end -->

</blockquote></details>
<details>
<summary>app/config/locale/countries.php (1)</summary><blockquote>

119-119: _⚠️ Potential issue_

**Fix typo in Latvia's name**

There appears to be a search/replace error in Latvia's name. "latitudevia" should be "Latvia".

```diff
-    'LV' => ['name' => 'latitudevia', 'latitude' => 57.0, 'longitude' => 25.0],
+    'LV' => ['name' => 'Latvia', 'latitude' => 57.0, 'longitude' => 25.0],
```

</blockquote></details>
<details>
<summary>app/config/locale/translations/eo.json (1)</summary><blockquote>

23-24: _⚠️ Potential issue_

**Incorrect Invitation Greeting Translation**  
The invitation greeting is set to `"Dankegon,"` instead of a greeting like “Saluton,”. This appears to be a copy/paste error—please correct the invitation hello line to an appropriate greeting.

</blockquote></details>
<details>
<summary>app/config/console.php (1)</summary><blockquote>

44-45: _💡 Verification agent_

<details>
<summary>🧩 Analysis chain</summary>

**Verify whitelisting logic for security**

The email and IP whitelisting implementation correctly parses comma-separated values, but consider adding input validation to ensure the values are properly formatted to prevent security issues.

---

🏁 Script executed:

```shell
#!/bin/bash
# Check if there's any pattern validation for the whitelist values
rg -A 3 -B 3 "WHITELIST_EMAILS|WHITELIST_IPS" --include="*.php"
```

Length of output: 507

---

🏁 Script executed:

```shell
#!/bin/bash
# Search for usage of whitelist config keys
rg -n "authWhitelist" --glob '*.php'

# Check for any email/IP validation using filter_var
rg -n "filter_var" --glob '*.php' | grep -E "FILTER_VALIDATE_EMAIL|FILTER_VALIDATE_IP"
```

Length of output: 2158

---



</details>

**Validate whitelist entries before use**

The console whitelist is currently parsed with `explode()` only, without trimming or validating each entry. To prevent misconfigurations or invalid values slipping through, please add proper validation:

• In **app/config/console.php**, wrap the exploded values in `array_map('trim', …)` and then filter them via `filter_var()` using `FILTER_VALIDATE_EMAIL` and `FILTER_VALIDATE_IP`.  
• Example diff:

```diff
-    'authWhitelistEmails' => (!empty(System::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null))) ? \explode(',', System::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null)) : [],
-    'authWhitelistIPs'    => (!empty(System::getEnv('_APP_CONSOLE_WHITELIST_IPS', null)))    ? \explode(',', System::getEnv('_APP_CONSOLE_WHITELIST_IPS', null))    : [],
+    'authWhitelistEmails' => array_filter(
+        array_map('trim', explode(',', System::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', ''))),
+        fn(string $email) => filter_var($email, FILTER_VALIDATE_EMAIL) !== false
+    ),
+    'authWhitelistIPs'    => array_filter(
+        array_map('trim', explode(',', System::getEnv('_APP_CONSOLE_WHITELIST_IPS', ''))),
+        fn(string $ip)    => filter_var($ip, FILTER_VALIDATE_IP) !== false
+    ),
```

This ensures only well-formed emails and IPs are allowed.  


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
    'authWhitelistEmails' => array_filter(
        array_map('trim', explode(',', System::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', ''))),
        fn(string $email) => filter_var($email, FILTER_VALIDATE_EMAIL) !== false
    ),
    'authWhitelistIPs'    => array_filter(
        array_map('trim', explode(',', System::getEnv('_APP_CONSOLE_WHITELIST_IPS', ''))),
        fn(string $ip)    => filter_var($ip,   FILTER_VALIDATE_IP)    !== false
    ),
`````

</details>

<!-- suggestion_end -->

</blockquote></details>
<details>
<summary>app/config/collections/common.php (2)</summary><blockquote>

1040-1043: _🛠️ Refactor suggestion_

**Index prefix length is far smaller than column size – please re-verify**

`providerUid` is declared with `size => 2048`, yet the unique index caps it to `128` bytes (`lengths => [ …, 128 ]`).  
That is usually done to stay within MySQL’s 3072-byte limit, but it also means two different provider UIDs that differ only after the 128-byte prefix will collide and throw a “duplicate key” error.

Double-check that 128 is sufficient for every provider UID you expect to store.  
If the full length is truly required, alternative strategies are:

1. Use a hash column (e.g. SHA-256) and index that.  
2. Switch the table/column charset to `ascii`/`latin1` to reduce byte width.

---

2374-2377: _⚠️ Potential issue_

**`$name` key will be silently ignored – should be `name`**

All other collections use the plain `name` key, e.g. `'name' => 'Cache'`.  
Here the dollar-prefixed variant (`'$name' => 'Files'`) breaks that convention and the runtime that consumes this config will most likely look for `name`, resulting in the collection label being lost.

```diff
-        '$id' => ID::custom('files'),
-        '$name' => 'Files',
+        '$id' => ID::custom('files'),
+        'name'  => 'Files',
```

</blockquote></details>
<details>
<summary>app/config/collections/projects.php (2)</summary><blockquote>

1630-1638: _🛠️ Refactor suggestion_

**Inconsistent collection/meta-ID conventions – pick one style and stick to it**  
Every other collection in this file wraps both `$collection` and `$id` with `ID::custom()`, e.g.

```php
'$collection' => ID::custom(Database::METADATA),
'$id'         => ID::custom('databases'),
```

but the `variables` collection uses the raw constant / string:

```php
'$collection' => Database::METADATA,
'$id'         => 'variables',
```

Besides hurting readability, this breaks the implicit guarantee that every identifier is namespaced through `ID::custom()`, and may cause collisions if another config file happens to reuse the same bare string.

```diff
-        '$collection' => Database::METADATA,
-        '$id' => 'variables',
+        '$collection' => ID::custom(Database::METADATA),
+        '$id' => ID::custom('variables'),
```

---

1144-1156: _⚠️ Potential issue_

**`lengths` missing for large VARCHAR keys – could break on MySQL 8 with utf8mb4**  
With the new `lengths` parameter now exposed by the API, omitting it for KEY indexes on wide‐string columns may push the underlying index past MySQL’s 3-byte / 767-byte limit (e.g. 255 × 3 B = 765 for utf8, but 4 × 255 = 1020 for utf8mb4).  

The following KEY indexes point to attributes sized `Database::LENGTH_KEY` (≈255) but have an empty `lengths` array:

* `_key_resource` (`resourceId`)
* `_key_resource_type` (`resourceType`)
* `_key_resource_internal_id` (`resourceInternalId`)
* `_key_deployment_internal_id` (`deploymentInternalId`)
* `_key_function_internal_id` (`functionInternalId`)
* `_key_resource_internal_id_resource_type` (multi-col)

Proposed fix (sample for one index; repeat for the others):

```diff
-   'lengths'   => [],
+   'lengths'   => [Database::LENGTH_KEY],
```

For the composite two-column index:

```diff
-   'lengths'   => [],
+   'lengths'   => [Database::LENGTH_KEY, 100],
```



Also applies to: 1186-1191, 1342-1347, 1620-1625, 1745-1750

</blockquote></details>
<details>
<summary>app/cli.php (1)</summary><blockquote>

301-301: _⚠️ Potential issue_

**Incorrect use of `Swoole\Coroutine\run()` – will throw at runtime**

`run()` expects a *callable*, but `\$cli->run(...)` returns the exit code (an `int`).  
Passing a non-callable value will raise `TypeError: Symfony\…\run() expects parameter 1 to be callable`.

```diff
-run($cli->run(...));
+run(static function () use ($cli): void {
+    $cli->run(...);
+});
```

This wraps the CLI execution inside the coroutine as intended.  



<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
run(static function () use ($cli): void {
    $cli->run(...);
});
`````

</details>

<!-- suggestion_end -->

</blockquote></details>
<details>
<summary>app/config/collections/platform.php (2)</summary><blockquote>

983-992: _🛠️ Refactor suggestion_

**Add the missing `json` filter to `realtime.value`**  
The TODO indicates the column stores structured JSON, yet no `json` filter is applied. Without it, the SDK will not automatically encode/decode and may leak invalid data.

```diff
-                'filters' => [], //TODO: use json filter
+                'filters' => ['json'],
```




<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
                '$id' => ID::custom('value'),
                'type' => Database::VAR_STRING,
                'format' => '',
                'size' => 16384,
                'signed' => true,
                'required' => true,
                'default' => null,
                'array' => false,
-                'filters' => [], //TODO: use json filter
+                'filters' => ['json'],
            ]
`````

</details>

<!-- suggestion_end -->

---

1255-1291: _⚠️ Potential issue_

**Token fields likely too small after encryption**  
`personalAccessToken` and `personalRefreshToken` are limited to 256 chars but are encrypted + base64-encoded (`encrypt` filter). Real-world GitHub/GitLab PATs are already ~40–120 chars; encrypted form frequently exceeds 300 chars.

```diff
-                'size' => 256,
+                'size' => 512,
```

Adjust both attributes (lines 1260-1268 & 1282-1291) to prevent truncation.

</blockquote></details>
<details>
<summary>app/config/specs/open-api3-1.6.x-client.json (1)</summary><blockquote>

7620-7644: _⚠️ Potential issue_

**Remove duplicate tag definitions**  
The `tags` array contains both `"projects"` and `"project"` with identical descriptions. This redundancy can lead to confusion and incorrect client code generation. Consolidate these into a single `"projects"` tag.

</blockquote></details>

</blockquote></details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T05:16:02Z
user: login: abnegate
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-13T05:38:17Z
user: login: abnegate
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-13T12:14:51Z
user: login: abnegate
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-14T01:23:41Z

Review comments:
diff_hunk: @@ -2901,10 +2899,11 @@ function updateAttribute(
                 throw new Exception(Exception::ATTRIBUTE_NOT_AVAILABLE, 'Attribute not available: ' . $oldAttributes[$attributeIndex]['key']);
             }
 
-            $lengths[$i] = null;
-
+            $lengths[$i] = array_key_exists($i, $lengths) ? $lengths[$i] : null;
path: app/controllers/api/databases.php
user: login: abnegate
body: Can be a bit simpler:

```suggestion
            $lengths[$i] ??= null
```
created_at: 2025-05-13T05:27:44Z
author_association: MEMBER
diff_hunk: @@ -2901,10 +2899,11 @@ function updateAttribute(
                 throw new Exception(Exception::ATTRIBUTE_NOT_AVAILABLE, 'Attribute not available: ' . $oldAttributes[$attributeIndex]['key']);
             }
 
-            $lengths[$i] = null;
-
+            $lengths[$i] = array_key_exists($i, $lengths) ? $lengths[$i] : null;
             if ($attributeArray === true) {
-                $lengths[$i] = Database::ARRAY_INDEX_LENGTH;
+                if ($lengths[$i] === null) {
+                    $lengths[$i] = Database::ARRAY_INDEX_LENGTH;
+                }
path: app/controllers/api/databases.php
user: login: abnegate
body: ```suggestion
                $lengths[$i] ??= Database::ARRAY_INDEX_LENGTH;
```
created_at: 2025-05-13T05:28:48Z
author_association: MEMBER
diff_hunk: @@ -2877,9 +2878,6 @@ function updateAttribute(
             'size' => 0
         ];
 
path: app/controllers/api/databases.php
user: login: abnegate
body: Let's validate here that lengths array is not longer than the attributes array, otherwise throw a new exception type: `Exception::INDEX_LENGTHS_INVALID` and in errors.php set the message to `Invalid index lengths. Count of lengths must be equal or less than the number of attributes.`
created_at: 2025-05-13T05:29:34Z
author_association: MEMBER
diff_hunk: @@ -2812,12 +2812,13 @@ function updateAttribute(
     ->param('key', null, new Key(), 'Index Key.')
     ->param('type', null, new WhiteList([Database::INDEX_KEY, Database::INDEX_FULLTEXT, Database::INDEX_UNIQUE]), 'Index type.')
     ->param('attributes', null, new ArrayList(new Key(true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of attributes to index. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' attributes are allowed, each 32 characters long.')
+    ->param('lengths', [], new ArrayList(new Integer(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Length of index. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE, optional:true)
     ->param('orders', [], new ArrayList(new WhiteList(['ASC', 'DESC'], false, Database::VAR_STRING), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of index orders. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' orders are allowed.', true)
path: app/controllers/api/databases.php
user: login: abnegate
body: Let's move the param after orders, so it's not a breaking change for SDKs without named parameters
created_at: 2025-05-13T05:31:37Z
author_association: MEMBER
diff_hunk: @@ -1422,9 +1422,40 @@ public function testCreateIndexes(array $data): array
         return $data;
     }
 
+
     /**
-     * @depends testCreateIndexes
+     * @depends testCreateAttributes
      */
+    public function testGetIndexByKeyWithLengths(array $data): void
+    {
+        $databaseId = $data['databaseId'];
+        $collectionId = $data['moviesId'];
+
+        $create = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/indexes", [
+            'content-type' => 'application/json',
+            'x-appwrite-project' => $this->getProject()['$id'],
+            'x-appwrite-key' => $this->getProject()['apiKey']
+        ], [
+            'key' => 'lengthTestIndex',
+            'type' => 'key',
+            'attributes' => ['title','description'],
+            'lengths' => [128,200]
+        ]);
+
+        $this->assertEquals(202, $create['headers']['status-code']);
+
+        $index = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/indexes/lengthTestIndex", [
+            'content-type' => 'application/json',
+            'x-appwrite-project' => $this->getProject()['$id'],
+            'x-appwrite-key' => $this->getProject()['apiKey']
+        ]);
+        $this->assertEquals(200, $index['headers']['status-code']);
+        $this->assertEquals('lengthTestIndex', $index['body']['key']);
+        $this->assertEquals([128,200], $index['body']['lengths']);
+    }
path: tests/e2e/Services/Databases/DatabasesBase.php
user: login: abnegate
body: Let's check some other cases as well:

- Lengths for array attributes get overridden correctly
- Lengths are assigned correctly when skipping some attributes (e.g. [null, null, 255] or [2 => 255])
- Count of lengths greater than count of attributes correctly throws 400
- Lengths too large throws 400 (total of all lengths should not exceed 768 for us, because we're using utf8mb4, 768 chars gives max 3072 bytes)
- Negative length values throws 400
- Any other failure cases you can think of

If you need to, add additional exception types + error messages to handle these cases
created_at: 2025-05-13T05:38:10Z
author_association: MEMBER
diff_hunk: @@ -1422,9 +1422,100 @@ public function testCreateIndexes(array $data): array
         return $data;
     }
 
+
     /**
-     * @depends testCreateIndexes
-     */
+ * @depends testCreateAttributes
+ */
+    public function testGetIndexByKeyWithLengths(array $data): void
+    {
+        $databaseId = $data['databaseId'];
+        $collectionId = $data['moviesId'];
+
+        // Test case for valid lengths
+        $create = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/indexes", [
+            'content-type' => 'application/json',
+            'x-appwrite-project' => $this->getProject()['$id'],
+            'x-appwrite-key' => $this->getProject()['apiKey']
+        ], [
+            'key' => 'lengthTestIndex',
+            'type' => 'key',
+            'attributes' => ['title','description'],
+            'lengths' => [128,200]
+        ]);
+        $this->assertEquals(202, $create['headers']['status-code']);
+
+        // Fetch index and check correct lengths
+        $index = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/indexes/lengthTestIndex", [
+            'content-type' => 'application/json',
+            'x-appwrite-project' => $this->getProject()['$id'],
+            'x-appwrite-key' => $this->getProject()['apiKey']
+        ]);
+        $this->assertEquals(200, $index['headers']['status-code']);
+        $this->assertEquals('lengthTestIndex', $index['body']['key']);
+        $this->assertEquals([128, 200], $index['body']['lengths']);
+
+        // Test case for lengths array overriding
+        $create = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/indexes", [
+            'content-type' => 'application/json',
+            'x-appwrite-project' => $this->getProject()['$id'],
+            'x-appwrite-key' => $this->getProject()['apiKey']
+        ], [
+            'key' => 'lengthOverrideTestIndex',
+            'type' => 'key',
+            'attributes' => ['title', 'description'],
path: tests/e2e/Services/Databases/DatabasesBase.php
user: login: abnegate
body: I don't think either of these is an array
created_at: 2025-05-13T12:14:51Z
author_association: MEMBER

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-05-13T05:07:46Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- This is an auto-generated comment: skip review by coderabbit.ai -->

> [!IMPORTANT]
> ## Review skipped
> 
> Auto reviews are disabled on base/target branches other than the default branch.
> 
> 
> 
> Please check the settings in the CodeRabbit UI or the `.coderabbit.yaml` file in this repository. To trigger a single review, invoke the `@coderabbitai review` command.
> 
> You can disable this status message by setting the `reviews.review_status` to `false` in the CodeRabbit configuration file.

<!-- end of auto-generated comment: skip review by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough

This update introduces new and refactored configuration files for database collection schemas, platform and project metadata, and the console project, enhancing structural clarity and maintainability. It also adds new environment variables, updates workflow automation, improves error handling, and expands runtime and OAuth provider support. Localization, documentation, Docker, and OpenAPI specs are updated for consistency and feature coverage.

## Changes

| File(s)                                                                                              | Change Summary |
|------------------------------------------------------------------------------------------------------|---------------|
| `.env`                                                                                               | Added and renamed environment variables for compression, domain deny list, rules format, S3 endpoint, maintenance, audit retention, stats, function abuse limits, and dual writing DBs. |
| `.github/workflows/publish.yml`, `.github/workflows/release.yml`                                     | Changed Docker Hub username source from secrets to repository variables in workflow configs. |
| `.github/workflows/tests.yml`                                                                        | Added jobs for database change detection and conditional E2E shared mode tests; updated actions versions; improved caching and permissions. |
| `.gitpod.yml`                                                                                        | Docker task runs with current user's UID/GID; removed Gitpod prebuilds configuration. |
| `CHANGES.md`                                                                                         | Added detailed changelog for version 1.6.1, listing new features, fixes, and improvements. |
| `CONTRIBUTING.md`                                                                                    | Updated usage metrics documentation and code snippets; added section on using preview domains locally. |
| `Dockerfile`                                                                                         | Updated base image, added `libwebp`, changed executable scripts, and refined conditional logic for extensions. |
| `README.md`, `README-CN.md`                                                                          | Updated Docker image tags to `1.6.2`; fixed section title in README.md. |
| `app/assets/security/10k-common-passwords`                                                           | Removed redundant "brien" and similar entries from password list. |
| `app/cli.php`                                                                                        | Refactored resource setup, renamed resources, added new resources for logs, executor, telemetry, and enhanced error logging. |
| `app/config/collections/common.php`, `app/config/collections/databases.php`, `app/config/collections/logs.php`, `app/config/collections/platform.php`, `app/config/collections/projects.php` | Added/defined new database collection schemas for common, platform, logs, databases, and projects. |
| `app/config/console.php`                                                                             | Added new console project configuration file with metadata, auth, and OAuth settings. |
| `app/config/errors.php`                                                                              | Added/removed/updated error codes and descriptions, including new resource and index errors. |
| `app/config/function-templates.php`                                                                  | Added Deno runtime, updated Node, Dart, and Bun versions, and improved function template definitions. |
| `app/config/locale/continents.php`, `app/config/locale/countries.php`                                | Changed from simple code lists to associative arrays with names and coordinates for continents and countries. |
| `app/config/locale/templates/email-inner-base.tpl`, `app/config/locale/templates/email-magic-url.tpl`, `app/config/locale/templates/email-mfa-challenge.tpl`, `app/config/locale/templates/email-otp.tpl`, `app/config/locale/templates/email-session-alert.tpl` | Removed trailing commas from greeting/thanks placeholders in email templates. |
| `app/config/locale/translations/*.json`                                                              | Standardized punctuation in greetings and thanks across many locale translation files; some files removed or added punctuation for consistency. |
| `app/config/oAuthProviders.php`                                                                      | Added Figma as a new OAuth provider configuration. |
| `app/config/platforms.php`                                                                           | Removed platform constants; updated SDK version numbers for all platforms. |
| `app/config/regions.php`                                                                             | Simplified configuration to a single default region. |
| `app/config/roles.php`                                                                               | Moved 'projects.write' scope from member to admin role. |
| `app/config/services.php`                                                                            | Removed `globalAttributes` from databases service configuration. |
| `app/config/specs/open-api3-1.6.x-client.json`, `app/config/specs/open-api3-latest-client.json`      | Updated OpenAPI specs: added endpoint grouping, improved descriptions, added Figma OAuth, new enums, and enhanced schema definitions. |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant User
    participant CLI
    participant Resources
    participant Database
    participant Publisher
    participant Executor
    participant Telemetry

    User->>CLI: Start CLI with task
    CLI->>Resources: Initialize resources (dbForPlatform, console, getLogsDB, etc.)
    CLI->>Database: Setup project/logs DB (with shared tables logic)
    CLI->>Publisher: Initialize queues (functions, deletes, stats, etc.)
    CLI->>Executor: Instantiate executor with host resolver
    CLI->>Telemetry: Setup telemetry (NoTelemetry)
    CLI->>CLI: Run task in Swoole coroutine
    CLI->>Resources: On error, call enhanced logError (with detailed info)
    CLI->>CLI: Clear timers on shutdown
```

## Possibly related PRs

- [appwrite/appwrite#9597](https://github.com/appwrite/appwrite/pull/9597): Modifies the value of `_APP_STATS_RESOURCES_INTERVAL`, which is also introduced and configured in this PR, indicating a direct relation to usage statistics interval configuration.

## Suggested reviewers

- eldadfux

## Poem

> In the burrow, I hop with glee,  
> New configs and schemas, as far as I see!  
> Deno joins the runtime crew,  
> Figma OAuth is shiny and new.  
> With commas in greetings, and logs in the night,  
> This bunny’s code garden is growing just right!  
> 🐇✨

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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= -->

<!-- internal state end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=appwrite/appwrite&utm_content=9748):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai explain this code block.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and explain its main purpose.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-05-13T05:09:41Z
body: ## Security Scan Results for PR

### Docker Image Scan Results

| Package | Version | Vulnerability | Severity |
|---------|---------|----------------|----------|
| binutils | 2.42-r0 | [CVE-2025-0840](https://nvd.nist.gov/vuln/detail/CVE-2025-0840) | HIGH |
| libexpat | 2.6.4-r0 | [CVE-2024-8176](https://nvd.nist.gov/vuln/detail/CVE-2024-8176) | HIGH |
| libxml2 | 2.12.7-r0 | [CVE-2024-56171](https://nvd.nist.gov/vuln/detail/CVE-2024-56171) | HIGH |
| libxml2 | 2.12.7-r0 | [CVE-2025-24928](https://nvd.nist.gov/vuln/detail/CVE-2025-24928) | HIGH |
| libxml2 | 2.12.7-r0 | [CVE-2025-27113](https://nvd.nist.gov/vuln/detail/CVE-2025-27113) | HIGH |
| sqlite-libs | 3.45.3-r1 | [CVE-2025-29087](https://nvd.nist.gov/vuln/detail/CVE-2025-29087) | HIGH |
| xz | 5.6.2-r0 | [CVE-2025-31115](https://nvd.nist.gov/vuln/detail/CVE-2025-31115) | HIGH |
| xz-libs | 5.6.2-r0 | [CVE-2025-31115](https://nvd.nist.gov/vuln/detail/CVE-2025-31115) | HIGH |
| golang.org/x/crypto | v0.31.0 | [CVE-2025-22869](https://nvd.nist.gov/vuln/detail/CVE-2025-22869) | HIGH |

### Source Code Scan Results

🎉 No vulnerabilities found!
author_association: NONE