8000 1.7.x by Meldiron · Pull Request #9649 · appwrite/appwrite · GitHub
[go: up one dir, main page]

Skip to content

1.7.x#9649

Merged
abnegate merged 1307 commits intomainfrom
1.7.x
May 18, 2025
Merged

1.7.x#9649
abnegate merged 1307 commits intomainfrom
1.7.x

Conversation

@Meldiron
Copy link
Contributor
@Meldiron Meldiron commented Apr 14, 2025

What does this PR do?

Test Plan

(Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work. Screenshots may also be helpful.)

Related PRs and Issues

  • (Related PR or issue)

Checklist

  • Have you read the Contributing Guidelines on issues?
  • 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?

Summary by CodeRabbit

  • New Features

    • Introduced Appwrite Sites: deploy and manage static sites with new site templates, frameworks, and build options.
    • Added support for site deployments, preview domains, and deployments management.
    • Enabled resource tokens for secure file and site access.
    • Expanded event system to include site and deployment events.
    • Added new 404 and enhanced error pages with improved branding and interactivity.
    • Added support for secret variables and dev keys for improved security and development workflows.
  • Improvements

    • Refined environment variable naming and configuration for domains, compute, and sites.
    • Enhanced storage health checks and added dedicated storage for sites and imports.
    • Updated Docker and Compose files with new volumes, services, and environment variables.
    • Improved OAuth provider configuration and SDK versioning.
    • Expanded permissions, roles, and scopes for sites, logs, and tokens.
    • Upgraded dependency versions and raised minimum PHP requirement to 8.3.
    • Improved routing, error handling, and preview authorization flows.
  • Bug Fixes

    • Enhanced validation for domain, IP, and resource token checks.
    • Fixed logic for file and membership access, owner counting, and database queries.
  • Documentation

    • Updated installation guides, contributing documentation, and environment variable descriptions.
  • Chores

    • Added new scripts and workflows for static analysis, benchmarking, and CI improvements.
    • Updated ignore rules for test resources and archives.

This release delivers Appwrite Sites, improved resource management, enhanced security, and a more robust developer experience.

@coderabbitai
Copy link
Contributor
coderabbitai bot commented Apr 14, 2025

Warning

Rate limit exceeded

@abnegate has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 9 minutes and 47 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 0d58bb8 and 33ac933.

📒 Files selected for processing (4)
  • .github/workflows/tests.yml (8 hunks)
  • app/init/resources.php (8 hunks)
  • app/views/install/compose.phtml (15 hunks)
  • docker-compose.yml (16 hunks)

Walkthrough

This update introduces extensive enhancements and refactoring across the platform. Major changes include the addition of new features for "Sites" (static site hosting and deployment), new configuration files for frameworks and templates, expanded environment variable support, and significant schema changes in collections to support new resource types and tokens. The routing, storage, and deployment logic have been unified and generalized for both functions and sites. The update also adds new error views, improved branding, and support for resource tokens, while modernizing workflows and dependencies.

Changes

File(s) / Path(s) Summary
.coderabbit.yaml Added CodeRabbit configuration file to control review path filters and auto-review triggers on specific branches.
.env, app/config/variables.php Renamed and reorganized environment variables, especially for routing, domains, compute, and maintenance. Added new variables for sites and compute, deprecated old ones, and updated descriptions and defaults.
.github/workflows/benchmark.yml Added new workflow for benchmarking PRs against the latest version, running benchmarks, and posting results as PR comments.
.github/workflows/cleanup-cache.yml, .github/workflows/codeql-analysis.yml, .github/workflows/linter.yml, .github/workflows/publish.yml, .github/workflows/release.yml Updated GitHub Actions workflows to use actions/checkout@v4 instead of v3. No logic changes.
.github/workflows/static-analysis.yml Added new workflow for Composer-based static analysis using PHPStan.
.github/workflows/tests.yml Enhanced test pipeline: added readiness checks for executor, expanded test matrix, split dev keys tests into dedicated jobs, removed benchmarking steps, and improved environment toggling.
.gitignore Added rule to ignore code.tar.gz files in /tests/resources/sites/.
CONTRIBUTING.md Added documentation for new HTTP modules structure, replacing monolithic controllers for better maintainability.
Dockerfile Added /storage/imports directory setup and included /usr/local/bin/screenshot in executable permissions.
README.md, README-CN.md Updated Docker image version in installation instructions to 1.7.0.
app/cli.php Integrated Swoole coroutine/timer management, updated runtime version, added telemetry resource, and improved error handling.
app/config/collections/common.php Added new attributes and indexes for identities, tokens, memberships, and targets to support scopes, expiration, and improved querying.
app/config/collections/platform.php Added new devKeys collection, extended projects/rules with new attributes and indexes, and improved indexing for multiple collections.
app/config/collections/projects.php Major schema changes: standardized deployment-related attributes, added new metadata fields, introduced resourceTokens collection, and expanded indexes for functions, sites, deployments, executions, variables, and migrations.
app/config/errors.php Added new error codes/messages for resources, tokens, functions, sites, builds, logs, and variables. Updated and corrected existing error codes and descriptions.
app/config/events.php Added new sites event category with nested deployments and related triggers.
app/config/frameworks.php Added new configuration file defining supported frameworks for sites, with build/runtime commands and adapters.
app/config/locale/templates/email-base-styled.tpl Replaced hardcoded styles and URLs with template variables for branding and dynamic content.
app/config/oAuthProviders.php Added class key specifying OAuth2 implementation class for each provider.
app/config/platforms.php Updated SDK versions for client, console, and server platforms.
app/config/roles.php Added new permission scopes for members and admins, including rules, sites, logs, and tokens.
app/config/runtimes.php Changed runtime version from 'v4' to 'v5' for retrieving runtimes.
app/config/scopes.php Added new scope entries for sites, logs, and tokens (read/write).
app/config/services.php Added new sites service, removed globalAttributes from databases, and marked functions as module-based.
app/config/specifications.php Updated import to new Specification namespace.
app/config/storage/inputs.php, app/config/storage/outputs.php Removed support for GIF file type and MIME mapping.
app/config/template-runtimes.php Added new config mapping runtime keys to names and supported versions for templates.
app/config/templates/function.php Replaced hardcoded runtimes with dynamic config, added score field to templates.
app/config/templates/site.php Added comprehensive site templates config, including frameworks, build commands, variables, and use cases.
app/config/variables.php Marked several variables as deprecated, introduced new ones for sites and compute, updated descriptions and defaults.
app/controllers/api/account.php Removed withRequestTimestamp wrappers, made OAuth2 provider class configurable, improved URL validation logic based on dev key, and updated abuse key labeling.
app/controllers/api/avatars.php Changed default/allowed range for quality parameter in image endpoints, improved QR code scaling and output quality.
app/controllers/api/console.php Enhanced domain validation logic, expanded environment variables in response, and updated variable names.
app/controllers/api/health.php Added deviceForSites to storage health checks and updated method signature accordingly.
app/controllers/api/migrations.php Added new /v1/migrations/csv endpoint for importing documents from CSV, with decryption/decompression support and migration queuing.
app/controllers/api/project.php Updated metrics queries to use resourceType/resourceInternalId, added secret boolean to variable create/update endpoints, enforced secret flag immutability.
app/controllers/api/projects.php Injected plan dependency into SMTP test email endpoint, enabling dynamic branding/social/legal links in email templates.
app/controllers/api/proxy.php Removed proxy rule creation endpoint, enhanced domain verification logic to support multiple DNS record types and composite validation.
app/controllers/api/storage.php Added resource token support for file access endpoints, updated SDK metadata, refined image preview quality parameter, and added comment for storage usage endpoint.
app/controllers/api/teams.php Improved URL validation logic in membership endpoints, refined owner count query, and removed withRequestTimestamp wrapper.
app/controllers/api/users.php Added support for filtering memberships with queries/search, and ensured cleanup of related identities/targets on user deletion.
app/controllers/api/vcs.php Generalized deployment logic for both functions and sites, added framework detection, improved preview rule creation, updated commit status URLs, and enhanced detection/repository listing endpoints.
app/controllers/general.php Major refactor of router logic: unified function/site handling, improved error/404 views, added preview authorization, enhanced CORS/origin validation, and modernized control flow.
app/controllers/shared/api.php Extended usage tracking for new events/collections, improved cache key handling, tightened resource token authorization, and added dev key bypass for abuse limits.
app/http.php Loaded public static files, added screenshots bucket, updated event handling, and improved domain filtering.
app/init/configs.php Reorganized configuration loading: added/removed config files for runtimes, templates, and specifications.
app/init/constants.php Added new branding, limits, metrics, and token resource type constants; updated/remapped metrics and resource types; incremented version/cache buster.
app/init/database/filters.php Added subQueryDevKeys filter, updated subQueryVariables to support both functions and sites.
app/init/registers.php Ensured PDO constants are fully qualified in database pool setup.
app/init/resources.php Added new resources for dev keys, resource tokens, sites/imports devices; updated cache and preview hostname resources.
app/views/general/404.phtml Added new, fully styled 404 error page template with dark/light mode support.
app/views/general/error.phtml Refactored error view: added Alpine.js, dynamic branding, improved error/trace display, and dark mode support.
app/views/install/compose.phtml, docker-compose.yml Added new volumes for imports/sites, updated environment variables for compute/sites, expanded domain targets, updated service images, and added appwrite-browser service.
app/worker.php Registered new resources for telemetry, sites/imports devices, plan, and improved error logging closure.
bin/screenshot Added new shell script to invoke screenshot CLI command.
composer.json Raised PHP requirement to 8.3.0, updated dependencies, added PHPStan and detector, enabled new plugins, and added check script.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Router
    participant DB
    participant Auth
    participant Executor
    participant Storage
    participant Sites
    participant Functions

    User->>Router: HTTP request (site/function)
    Router->>DB: Lookup rule/domain/resource
    alt Site resource
        Router->>Auth: Check preview JWT (if preview)
        Auth-->>Router: Authorized/Unauthorized
        Router->>Sites: Serve static/SSR site or preview
        Sites-->>Router: Site response
    else Function resource
        Router->>Auth: Check permissions
        Auth-->>Router: Authorized/Unauthorized
        Router->>Executor: Run function with runtime/spec
        Executor-->>Router: Function response
    end
    Router->>Storage: (Optional) Serve file/resource
    Storage-->>Router: File/Resource
    Router->>User: Response (with error/404 views if needed)
Loading

Poem

🐇
A hop, a skip, a leap so wide,
Now Appwrite hosts your static site!
With tokens, rules, and modules new,
The rabbit’s code has grown and grew.
Frameworks, branding, error flair—
Deployments handled with extra care.
Onward we bound, with Sites in view!

✨ Finishing Touches
  • 📝 Generate Docstrings

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • 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 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 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.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions
Copy link
github-actions bot commented Apr 14, 2025

Security Scan Results for PR

Docker Image Scan Results

Package Version Vulnerability Severity
binutils 2.42-r0 CVE-2025-0840 HIGH
libexpat 2.6.4-r0 CVE-2024-8176 HIGH
libxml2 2.12.7-r0 CVE-2024-56171 HIGH
libxml2 2.12.7-r0 CVE-2025-24928 HIGH
libxml2 2.12.7-r0 CVE-2025-27113 HIGH
libxml2 2.12.7-r0 CVE-2025-32414 HIGH
libxml2 2.12.7-r0 CVE-2025-32415 HIGH
sqlite-libs 3.45.3-r1 CVE-2025-29087 HIGH
xz 5.6.2-r0 CVE-2025-31115 HIGH
xz-libs 5.6.2-r0 CVE-2025-31115 HIGH
golang.org/x/crypto v0.31.0 CVE-2025-22869 HIGH

Source Code Scan Results

🎉 No vulnerabilities found!

@pkg-pr-new
Copy link
pkg-pr-new bot commented Apr 14, 2025

Open in StackBlitz

npm i https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@9649

commit: 33ac933

@github-actions
Copy link
github-actions bot commented Apr 14, 2025

✨ Benchmark results

  • Requests per second: 1,018
  • Requests with 200 status code: 183,283
  • P99 latency: 0.185526166

⚡ Benchmark Comparison

Metric This PR Latest version
RPS 1,018 1,295
200 183,283 233,077
P99 0.185526166 0.142897333

@abnegate abnegate changed the base branch from 1.6.x to main May 18, 2025 12:44
@abnegate abnegate marked this pull request as ready for review May 18, 2025 12:45
Copy link
Contributor
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 23

🔭 Outside diff range comments (4)
app/cli.php (1)

296-302: ⚠️ Potential issue

Fatal syntax & coroutine misuse

run($cli->run(...)); is syntactically invalid (... needs a variadic argument) and passes the result of $cli->run() instead of a callable to Swoole\Coroutine\run().

This prevents the CLI from starting.

Suggested fix:

- run($cli->run(...));
+run(static function () use ($cli, $args) {
+    // Swoole coroutine context; propagate original argv
+    $cli->run(...$args);
+});

Also ensure $args is defined in that scope (add global/use).

composer.json (1)

47-77: 💡 Verification agent

🧩 Analysis chain

Package dependency updates improve framework capabilities.

Multiple package dependencies have been updated, including the addition of utopia-php/detector. These updates likely provide bug fixes, new features, and improved compatibility with PHP 8.3.


🏁 Script executed:

#!/bin/bash
# Check if there are breaking changes in the major dependency updates
grep "utopia-php/" composer.json | awk -F':' '{print $1}' | tr -d ' ",' | xargs -I{} sh -c 'echo "Checking {}"; curl -s "https://api.github.com/repos/{}/releases" | grep -E "tag_name|body" | head -n 10'

Length of output: 29575


Attention: Breaking changes introduced by some updated dependencies

While most of the updated packages include minor fixes or new features, a couple require code adjustments in consumers:

  • utopia-php/locale (v0.6.0)

    • Placeholder syntax in Locale::getText() has changed from {name} to {{name}}. You’ll need to update any calls or fixture data using the old syntax.
    • See full breaking-change notes in the release body.
  • utopia-php/orchestration (v0.16.0)

    • getStats() no longer throws on missing container stats; it returns an empty array (or partial results). Update any exception-handling or error-path logic that expected an exception.

Please review your codebase for usages of these methods and adjust accordingly before merging.

app/controllers/api/teams.php (1)

458-470: 🛠️ Refactor suggestion

url parameter validation – possible open redirect in dev mode
The dynamic validator selection is great, but when devKey is provided the code falls back to new URL() which permits all hosts and schemes. In practice this means a malicious client can craft an invite link that redirects unsuspecting users anywhere.

->param('url', '', fn ($clients, $devKey) => $devKey->isEmpty() ? new Host($clients) : new URL(), ... )

Recommendation:

-    return $devKey->isEmpty() ? new Host($clients) : new URL();
+    return $devKey->isEmpty()
+        ? new Host($clients)
+        : new URL(['https', 'http']); // restrict schemes

Also consider emitting a log entry when URL mode is used so it’s visible in audit logs.
[security]

app/controllers/api/vcs.php (1)

1545-1549: ⚠️ Potential issue

Fatal bug: argument count mismatch when calling $createGitDeployments

$createGitDeployments() expects 19 parameters; this call supplies only 11 – PHP will throw ArgumentCountError and break the authorize flow.

-        $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerCommitHash, $providerPullRequestId, true, $dbForPlatform, $queueForBuilds, $getProjectDB, $request);
+        $createGitDeployments(
+            $github,
+            $providerInstallationId,
+            $repositories,
+            $providerBranch,
+            '',                        // $providerBranchUrl
+            $repositoryName,           // $providerRepositoryName
+            '',                        // $providerRepositoryUrl
+            $owner,                    // $providerRepositoryOwner
+            $providerCommitHash,
+            $commitDetails['commitAuthor'] ?? '',
+            $commitDetails['authorUrl'] ?? '',
+            $commitDetails['commitMessage'] ?? '',
+            $providerCommitUrl,
+            $providerPullRequestId,
+            true,                      // external
+            $dbForPlatform,
+            $queueForBuilds,
+            $getProjectDB,
+            $request
+        );

Alternatively, refactor the helper to accept a DeploymentContext object to stop this brittleness.

🧹 Nitpick comments (39)
.coderabbit.yaml (1)

11-11: Add newline at end of file.
YAMLlint reports a missing newline character at EOF. Please ensure the file ends with a newline to satisfy POSIX conventions.

🧰 Tools
🪛 YAMLlint (1.37.1)

[error] 11-11: no new line character at the end of file

(new-line-at-end-of-file)

app/init/registers.php (1)

220-224: Fully qualify global PDO attribute constants
Using \PDO::ATTR_* avoids namespace collisions. To reduce duplication and ensure consistency across the codebase, consider using SQL::getPDOAttributes() here instead of hardcoding the attribute array.

- return new PDO("mysql:host={$dsnHost};port={$dsnPort};dbname={$dsnDatabase};charset=utf8mb4", $dsnUser, $dsnPass, array(
-     \PDO::ATTR_TIMEOUT => 3,
-     \PDO::ATTR_PERSISTENT => false,
-     \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
-     \PDO::ATTR_EMULATE_PREPARES => true,
-     \PDO::ATTR_STRINGIFY_FETCHES => true
- ));
+ return new PDO(
+     "mysql:host={$dsnHost};port={$dsnPort};dbname={$dsnDatabase};charset=utf8mb4",
+     $dsnUser,
+     $dsnPass,
+     SQL::getPDOAttributes()
+ );
bin/screenshot (1)

1-3: Use exec and properly quote arguments in wrapper
To forward signals correctly and handle arguments with spaces safely, update the script as follows:

- #!/bin/sh
- php /usr/src/code/app/cli.php screenshot $@
+ #!/bin/sh
+ exec php /usr/src/code/app/cli.php screenshot "$@"
app/config/template-runtimes.php (1)

3-5: TODO comment needs a timeline or tracking issue

The TODO comment indicates this is a temporary solution that should be replaced with direct usage of runtimes.php, but doesn't specify when this should happen or reference a tracking issue.

Consider adding a reference to an issue tracking this technical debt or providing a more specific timeline:

-// TODO: Remove, replace with runtimes.php directly
+// TODO: Remove, replace with runtimes.php directly (Issue #XXXX)
// Used in function templates and site frameworks
.github/workflows/static-analysis.yml (1)

1-16: New static analysis workflow provides additional code quality checks

The workflow runs PHPStan (via Composer's check command) inside a Docker container, adding an important static analysis pipeline to improve code quality assurance. This complements the other CI workflows and ensures code quality is validated on pull requests.

Add a newline at the end of the file to fix the YAML linting error:

  docker run --rm -v $PWD:/app composer:2.6 sh -c \
  "composer install --profile --ignore-platform-reqs && composer check"
+
🧰 Tools
🪛 YAMLlint (1.37.1)

[error] 16-16: no new line character at the end of file

(new-line-at-end-of-file)

app/config/services.php (1)

173-177: Subtitle grammar / clarity

Missing infinitive “to” and a small readability tweak:

-        'subtitle' => 'The Sites Service allows you view, create and manage your web applications.',
+        'subtitle' => 'The Sites service allows you to view, create, and manage your web applications.',
app/views/general/404.phtml (3)

9-15: Remote font import can block first paint

Using @import url(https://fonts.bunny.net/…) inside <style> forces the browser to wait for the CSS download before rendering, which delays the 404 page (often the first thing crawlers/users see).

Two lightweight options:

-    @import url(https://fonts.bunny.net/css?family=fira-code:400|inter:400);
+    /* Self-host or defer fonts to avoid blocking render. */
+    /* @import url('…'); */

Or move the import to a separate <link rel="preload"> / <link rel="stylesheet"> in the <head>.


157-182: Add accessible labelling for decorative SVG logos

The two <svg> logos are purely decorative but don’t declare their intent. Screen readers will attempt to parse every path.

Add either aria-hidden="true" or a descriptive label/role:

-<svg class="logo-dark" width="110" height="20" …>
+<svg class="logo-dark" width="110" height="20" role="img" aria-label="Appwrite logo" …>

Repeat for the light variant.

This keeps the page WCAG-friendly with near-zero cost.


4-6: Consider no-index meta tag

A 404 page is not useful to search engines and can pollute the index if users link to invalid URLs. You can signal this directly:

<meta name="robots" content="noindex">

Place it alongside the viewport meta tag.

CONTRIBUTING.md (2)

166-187: Well-structured module documentation improves architecture guidance.

The new Modules section provides clear guidance on the modern architectural approach for organizing service endpoints, moving away from large controller files to a more maintainable and RESTful structure. The examples and organization rules will help contributors follow consistent patterns.

There are a few minor grammatical issues that could be improved:

  • Line 168: Add "the" before "approach" → "we noticed the approach of having"
  • Line 168: Fix verb agreement in "Not only it creates" → "Not only does it create"
  • Line 168: Add "the" before "product's" → "all the product's features"
  • Line 172: Add "the" before "below" → "follows the below structure"
  • Line 180: Add "a" before "resource" → "doesn't have a resource"
🧰 Tools
🪛 LanguageTool

[uncategorized] ~168-~168: You might be missing the article “the” here.
Context: ... Modules As Appwrite grows, we noticed approach of having all service endpoints in `app...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~168-~168: This verb does not appear to agree with the subject. Consider using a different form.
Context: ...].php` is not maintainable. Not only it creates massive files, it also doesnt contain a...

(AI_EN_LECTOR_REPLACEMENT_VERB_AGREEMENT)


[uncategorized] ~168-~168: You might be missing the article “the” here.
Context: ...ssive files, it also doesnt contain all product's features such as workers or tasks. Wh...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~172-~172: You might be missing the article “the” here.
Context: ... Endpoints Every endpoint file follows below structure, making it consistent with HT...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~180-~180: You might be missing the article “the” here.
Context: ...ction].php ``` Tips and tricks: 1. If endpoint doesn't have resource, use service name...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~180-~180: You might be missing the article “a” here.
Context: ...sn't have resource, use service name as resource name too > Example: `Modules/Sites/Http...

(AI_EN_LECTOR_MISSING_DETERMINER_A)

🪛 markdownlint-cli2 (0.17.2)

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

(MD040, fenced-code-language)


174-176: Add language identifier to fenced code block.

For better syntax highlighting and documentation standards, specify a language for the code block.

-```
+```php
src/Appwrite/Platform/Modules/[service]/Http/[resource]/[action].php
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

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

(MD040, fenced-code-language)

app/worker.php (1)

338-339: telemetry resource hard-codes NoTelemetry
Returning new NoTelemetry() disables telemetry for all workers, regardless of the project’s configuration or any future feature flags. If disable-telemetry is the desired default, consider reading an env var (e.g. _APP_TELEMETRY_DISABLED) so that operators can opt-in later without code changes.

app/config/frameworks.php (1)

18-312: High duplication across adapter definitions
Most framework entries repeat the same keys (buildRuntime, runtimes, identical static adapter definitions, etc.). Consider extracting shared defaults:

$defaults = [
    'screenshotSleep' => 3000,
    'buildRuntime'    => 'node-22',
    'runtimes'        => getVersions($templateRuntimes['NODE']['versions'], 'node'),
];

return [
    'react' + $defaults + [...],
    ...
];

This reduces maintenance burden when build commands change.

app/controllers/api/proxy.php (1)

245-253: Minor: optimise diagnostics aggregation

$validator->getLogs() already returns a concatenated string; wrapping it inside an array and implode() may print “Array” or duplicate line-breaks.
You can simplify:

- foreach ($validators as $validator) {
-     if (!empty($validator->getLogs())) {
-         $errors[] = $validator->getLogs();
-     }
- }
- $error = \implode("\n", $errors);
+ foreach ($validators as $validator) {
+     $logs = $validator->getLogs();
+     if (!empty($logs)) {
+         $errors[] = $logs;
+     }
+ }
+ $error = \implode("\n", $errors);

Very small gain, but keeps the log payload predictable.

app/config/collections/common.php (1)

1105-1125: scopes / expire attribute sizes & missing index

  1. Database::LENGTH_KEY is typically 128 chars; several scopes (storage.files.read, databases.collections.documents.read, …) already exceed that.
    Consider increasing to 255 or use 0 (unlimited) if there is no DB limitation.

  2. Access patterns for identities frequently query by expiry (expire < now()). Adding a simple index speeds up clean-up jobs:

+ [
+     '$id'        => ID::custom('_key_expire'),
+     'type'       => Database::INDEX_KEY,
+     'attributes' => ['expire'],
+     'lengths'    => [],
+     'orders'     => [Database::ORDER_ASC],
+ ],
.github/workflows/benchmark.yml (1)

61-67: Replace custom APT repo with a pinned static binary for oha
Adding external repositories increases build time and occasionally fails due to key-server / mirror issues.
oha provides pre-built static binaries that can be fetched in one line:

-          echo "deb [signed-by=/usr/share/keyrings/azlux-archive-keyring.gpg] http://packages.azlux.fr/debian/ stable main" | sudo tee /etc/apt/sources.list.d/azlux.list
-          sudo wget -O /usr/share/keyrings/azlux-archive-keyring.gpg https://azlux.fr/repo.gpg
-          sudo apt update
-          sudo apt install oha
+          curl -Lo /usr/local/bin/oha \
+            https://github.com/hatoo/oha/releases/download/v0.6.4/oha-linux-amd64 \
+          && chmod +x /usr/local/bin/oha

Benefits: faster, no root privileges, fewer moving parts, and deterministic versioning.

app/views/general/error.phtml (1)

43-44: Typo: “occured” → “occurred”
Minor copy-editing fix to maintain a professional UI.

-        $message = $code >= 500 ? 'An unexpected server error occured.' : 'An unexpected client error occured.';
+        $message = $code >= 500 ? 'An unexpected server error occurred.' : 'An unexpected client error occurred.';
app/config/errors.php (2)

491-506: Token messages reference “file token” but cover generic resource tokens
Descriptions for TOKEN_NOT_FOUND & friends mention “file token”, yet the new token system is generic (APIs, storage, etc.).
Updating wording avoids confusion:

-        'description' => 'The requested file token could not be found.',
+        'description' => 'The requested resource token could not be found.',

-        'description' => 'The requested file token has expired.',
+        'description' => 'The requested resource token has expired.',

605-614: Code 400 for BUILD_FAILED & BU B94A ILD_CANCELED may hide server errors
A build failure often implies an internal error (dependency fetch, build pipeline, etc.).
Returning 5xx (e.g., 502/500) helps clients distinguish user input problems (4xx) from server-side issues.

Consider:

-        'code' => 400,
+        'code' => 500,

for one or both errors, or at least document the rationale.

.github/workflows/tests.yml (2)

125-132: Busy-wait loop may consume runner time + logs

The tight while ! grep …; do sleep 1; done loop polls Docker logs every second.
Consider:

  • Adding set -eo pipefail so the step fails on pipe errors.
  • Increasing sleep 2-3 or using --tail 1 -f to reduce log spam.
  • Bailing out early when the container exits unexpectedly.

Example:

-while ! docker compose logs openruntimes-executor | grep -q "Executor is ready."; do
-  echo "Waiting for Executor to come online"
-  sleep 1
-done
+set -eo pipefail
+timeout 180 bash -c '
+  until docker compose logs --tail 1 openruntimes-executor | grep -q "Executor is ready."; do
+    sleep 3
+  done
+'
🧰 Tools
🪛 YAMLlint (1.37.1)

[error] 125-125: trailing spaces

(trailing-spaces)


124-127: Trailing whitespace – YAMLLint errors

YAMLLint flags lines 125 and 276 for trailing spaces.
While harmless, they fail stricter CI linters – please trim them.

Also applies to: 276-276

🧰 Tools
🪛 YAMLlint (1.37.1)

[error] 125-125: trailing spaces

(trailing-spaces)

app/controllers/shared/api.php (2)

540-545: Listener registration duplicates nearly-identical callbacks

Each on(Database::EVENT_…) supplies an identical closure.
Reduce boilerplate and risk of missed events:

foreach ([
    Database::EVENT_DOCUMENT_CREATE,
    Database::EVENT_DOCUMENT_DELETE,
    Database::EVENT_DOCUMENTS_CREATE,
    Database::EVENT_DOCUMENTS_DELETE,
    Database::EVENT_DOCUMENTS_UPSERT,
] as $evt) {
    $dbForProject->on($evt, 'calculate-usage', fn ($e, $doc) =>
        $usageDatabaseListener($e, $doc, $queueForStatsUsage)
    );
}

This keeps the event list in one place and simplifies future maintenance.


95-109: Minor: clarify bulk-event value derivation

Using $document->getAttribute('modified', 0) / 'created' for bulk events is correct but non-obvious.
A short inline comment (e.g., “// contains count of affected docs”) would aid future readers.

app/controllers/api/storage.php (4)

946-951: Documentation & validator disagree on allowed quality range

The validator now permits -1..100, but the description still says “Pass an integer between 0 to 100”.

- 'Preview image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.'
+ 'Preview image quality. Pass -1 to keep the existing image quality, or an integer between 0 and 100 to override it.'

Without the update, SDKs may generate the wrong docs and users will assume -1 is invalid.


976-983: Authorization flow: small optimisation opportunity

$isToken is computed before $file is fetched, but the later internal-ID
check ($resourceToken->getAttribute('fileInternalId')) is what finally
decides authorisation.
We always hit the database even when the token ultimately mismatches.

Consider short-circuiting earlier:

if (!$resourceToken->isEmpty()
    && $resourceToken->getAttribute('bucketInternalId') === $bucket->getInternalId()
    && $resourceToken->getAttribute('fileInternalId') === $fileInternalId /* param */) {
   $isToken = true;
}

Not critical, but would save an unnecessary DB read on invalid tokens.


1153-1160: Repeated token-authorisation logic – extract to helper for consistency

The tri-state check ($fileSecurity, bucket perms, token validity) is duplicated
across preview, download, and view. Centralising it (e.g. a
TokenAuthorizer::canAccess($bucket, $file, $resourceToken)) would:

  • Reduce chances of divergent logic in future edits.
  • Make unit-testing the edge-cases (expired token, wrong bucket, etc.) easier.

Not a blocker for this PR, but worth considering.

Also applies to: 1310-1315


1810-1811: Great to see usage endpoint comment – please keep doc-block style consistent

For in-file navigation tools it helps if section headers follow the project’s
PHPDoc style (/** … */). Minor consistency nit.

app/init/resources.php (1)

508-510: Unused injected dependency

Telemetry $telemetry is injected into deviceForLocal but never referenced.
If the intention is just to ensure the telemetry resource is initialised, add a clarifying comment. Otherwise drop the parameter to avoid confusion.

app/config/variables.php (1)

109-117: Deprecated variable still marked as required

_APP_DOMAIN_TARGET is flagged “Deprecated since 1.7.0” yet required => true.
This forces users to set a value that the code path no longer consumes.

Consider switching required to false (or removing it on the next major) to avoid confusion.

app/config/templates/site.php (1)

169-173: Fail fast when an unknown framework enum is supplied

getFramework() will raise a PHP warning (undefined index) and return null if the caller passes an invalid $frameworkEnum.
Making the failure explicit reduces debugging time:

-function getFramework(string $frameworkEnum, array $overrides)
-{
-    $settings = \array_merge(TEMPLATE_FRAMEWORKS[$frameworkEnum], $overrides);
-    return $settings;
+function getFramework(string $frameworkEnum, array $overrides): array
+{
+    if (!\array_key_exists($frameworkEnum, TEMPLATE_FRAMEWORKS)) {
+        throw new \InvalidArgumentException("Unknown framework '$frameworkEnum'");
+    }
+
+    return \array_merge(TEMPLATE_FRAMEWORKS[$frameworkEnum], $overrides);
 }
app/init/constants.php (2)

33-38: New batch-limit & token expiry constants – double-check configurability

APP_LIMIT_DATABASE_BATCH and APP_RESOURCE_TOKEN_ACCESS are hard-coded.
Consider wiring them to env vars (with sane defaults) to avoid recompiling when scaling large imports or rotating tokens faster.


194-255: Metric namespace explosion – recommend grouping

Dozens of new metric patterns are added for sites & generic resources.
Long, copy-pasted constant names are error-prone and inflate opcode cache.

Suggestion: expose a single helper like metric("sites", "requests", $siteId) to build strings on-demand, drop the static constants, and cut maintenance cost by ~200 lines.

app/controllers/api/vcs.php (2)

212-221: Repeated string concatenation – consider implode once

$commands[] then implode(' && ', $commands) works, but for long lists use array_filter first to skip empties instead of multiple if (!empty()) guards.

$commands = \array_filter([
    $resource->getAttribute('installCommand', ''),
    $resource->getAttribute('buildCommand', ''),
    $resource->getAttribute('commands', ''),
]);
$buildCommands = implode(' && ', $commands);

266-356: Preview-rule creation is duplicated three times

Branch, commit and generic preview rules share ~95 % identical code.
Extract into a small createRule($domain, array $extras) helper to remove ~60 lines and centralise error handling.

app/config/collections/platform.php (1)

731-830: devKeys collection: missing uniqueness & retention guarantees

Nice addition 👍, yet a few gaps:

  1. name should be UNIQUE per project to avoid ambiguous keys.
  2. secret is encrypted but still queryable; add lengths = [512] to _key_project if you intend to query by secret hash.
  3. Consider a TTL index on expire to auto-purge expired dev-keys (supported in both MariaDB & Mongo back-end).

Example diff for uniqueness:

+[
+    '$id'        => ID::custom('_key_project_name'),
+    'type'       => Database::INDEX_UNIQUE,
+    'attributes' => ['projectInternalId', 'name'],
+    'lengths'    => [Database::LENGTH_KEY, Database::LENGTH_KEY],
+    'orders'     => [Database::ORDER_ASC , Database::ORDER_ASC],
+],
app/controllers/general.php (3)

296-303: Variable shadowing: $version overwritten

$version is set at L296 and then re-declared inside the try block at L489-497.
While PHP allows this, it harms readability and makes later maintenance error-prone (which version is it now?).

Rename the inner variable or re-use the original:

-            $version = match ($type) {
+            $execVersion = match ($type) {

Then pass $execVersion to the executor.


489-525: Duplicate computation of $entrypoint & $runtimeEntrypoint

$entrypoint is defined twice (L493-497 and L519-523) with identical logic. This can drift out of sync.

Extract a helper:

$entrypoint = ($type === 'function') ? $deployment->getAttribute('entrypoint', '') : '';

and reuse.


1102-1105: Duplicate header injection

Access-Control-Allow-Origin: * is added again in the OPTIONS handler. If the earlier GET/POST handler already injected it, this leads to duplicate headers (harmless but noisy).

Move the wildcard logic into a small helper that guarantees single injection.

app/config/collections/projects.php (1)

846-851: Empty lengths in single-column indexes – safe but inconsistent

Several new single-column indexes omit the lengths array altogether. While allowed, other parts of the file specify explicit lengths, so the style is inconsistent.

Consider setting the length explicitly (or omitting it everywhere) for maintainability.

Also applies to: 1281-1286, 1758-1769, 1785-1790

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between ac77c15 and 0d58bb8.

⛔ Files ignored due to path filters (235)
  • app/config/specs/open-api3-1.5.x-client.json is excluded by !app/config/specs/**
  • app/config/specs/open-api3-1.5.x-console.json is excluded by !app/config/specs/**
  • app/config/specs/open-api3-1.5.x-server.json is excluded by !app/config/specs/**
  • app/config/specs/open-api3-1.6.x-client.json is excluded by !app/config/specs/**
  • app/config/specs/open-api3-1.6.x-console.json is excluded by !app/config/specs/**
  • app/config/specs/open-api3-1.6.x-server.json is excluded by !app/config/specs/**
  • app/config/specs/open-api3-1.7.x-client.json is excluded by !app/config/specs/**
  • app/config/specs/open-api3-1.7.x-console.json is excluded by !app/config/specs/**
  • app/config/specs/open-api3-1.7.x-server.json is excluded by !app/config/specs/**
  • app/config/specs/open-api3-latest-client.json is excluded by !app/config/specs/**
  • app/config/specs/open-api3-latest-console.json is excluded by !app/config/specs/**
  • app/config/specs/open-api3-latest-server.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-1.5.x-client.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-1.5.x-console.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-1.5.x-server.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-1.6.x-client.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-1.6.x-console.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-1.6.x-server.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-1.7.x-client.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-1.7.x-console.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-1.7.x-server.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-latest-client.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-latest-console.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-latest-server.json is excluded by !app/config/specs/**
  • composer.lock is excluded by !**/*.lock
  • docs/examples/1.6.x/server-dart/examples/databases/create-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-dart/examples/databases/delete-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-dart/examples/databases/update-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-dart/examples/databases/upsert-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-deno/examples/databases/create-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-deno/examples/databases/delete-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-deno/examples/databases/update-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-deno/examples/databases/upsert-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-dotnet/examples/databases/create-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-dotnet/examples/databases/delete-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-dotnet/examples/databases/update-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-dotnet/examples/databases/upsert-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-go/examples/databases/create-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-go/examples/databases/delete-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-go/examples/databases/update-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-go/examples/databases/upsert-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-graphql/examples/databases/create-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-graphql/examples/databases/delete-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-graphql/examples/databases/update-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-graphql/examples/databases/upsert-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-kotlin/java/databases/create-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-kotlin/java/databases/delete-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-kotlin/java/databases/update-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-kotlin/java/databases/upsert-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-kotlin/kotlin/databases/create-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-kotlin/kotlin/databases/delete-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-kotlin/kotlin/databases/update-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-kotlin/kotlin/databases/upsert-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-nodejs/examples/databases/create-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-nodejs/examples/databases/delete-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-nodejs/examples/databases/update-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-nodejs/examples/databases/upsert-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-php/examples/databases/create-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-php/examples/databases/delete-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-php/examples/databases/update-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-php/examples/databases/upsert-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-python/examples/databases/create-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-python/examples/databases/delete-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-python/examples/databases/update-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-python/examples/databases/upsert-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-rest/examples/databases/create-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-rest/examples/databases/delete-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-rest/examples/databases/update-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-rest/examples/databases/upsert-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-ruby/examples/databases/create-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-ruby/examples/databases/delete-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-ruby/examples/databases/update-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-ruby/examples/databases/upsert-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-swift/examples/databases/create-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-swift/examples/databases/delete-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-swift/examples/databases/update-documents.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-swift/examples/databases/upsert-documents.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/create-anonymous-session.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/create-email-password-session.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/create-email-token.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/create-j-w-t.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/create-magic-u-r-l-token.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/create-mfa-authenticator.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/create-mfa-challenge.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/create-mfa-recovery-codes.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/create-o-auth2session.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/create-o-auth2token.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/create-phone-token.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/create-phone-verification.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/create-push-target.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/create-recovery.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/create-session.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/create-verification.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/create.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/delete-identity.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/delete-mfa-authenticator.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/delete-push-target.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/delete-session.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/delete-sessions.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/get-mfa-recovery-codes.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/get-prefs.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/get-session.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/get.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/list-identities.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/list-logs.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/list-mfa-factors.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/list-sessions.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/update-email.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/update-m-f-a.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/update-magic-u-r-l-session.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/update-mfa-authenticator.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/update-mfa-challenge.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/update-mfa-recovery-codes.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/update-name.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/update-password.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/update-phone-session.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/update-phone-verification.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/update-phone.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/update-prefs.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/update-push-target.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/update-recovery.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/update-session.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/update-status.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/account/update-verification.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/avatars/get-browser.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/avatars/get-credit-card.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/avatars/get-favicon.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/avatars/get-flag.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/avatars/get-image.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/avatars/get-initials.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/avatars/get-q-r.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/databases/create-document.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/databases/delete-document.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/databases/get-document.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/databases/list-documents.md is excluded by !docs/examples/**
  • < 5276 code class="notranslate">docs/examples/1.7.x/client-android/java/databases/update-document.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/functions/create-execution.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/functions/get-execution.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/functions/list-executions.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/graphql/mutation.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/graphql/query.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/locale/get.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/locale/list-codes.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/locale/list-continents.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/locale/list-countries-e-u.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/locale/list-countries-phones.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/locale/list-countries.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/locale/list-currencies.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/locale/list-languages.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/messaging/create-subscriber.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/messaging/delete-subscriber.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/storage/create-file.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/storage/delete-file.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/storage/get-file-download.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/storage/get-file-preview.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/storage/get-file-view.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/storage/get-file.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/storage/list-files.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/storage/update-file.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/teams/create-membership.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/teams/create.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/teams/delete-membership.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/teams/delete.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/teams/get-membership.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/teams/get-prefs.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/teams/get.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/teams/list-memberships.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/teams/list.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/teams/update-membership-status.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/teams/update-membership.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/teams/update-name.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/java/teams/update-prefs.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/create-anonymous-session.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/create-email-password-session.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/create-email-token.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/create-j-w-t.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/create-magic-u-r-l-token.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/create-mfa-authenticator.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/create-mfa-challenge.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/create-mfa-recovery-codes.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/create-o-auth2session.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/create-o-auth2token.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/create-phone-token.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/create-phone-verification.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/create-push-target.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/create-recovery.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/create-session.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/create-verification.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/create.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/delete-identity.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/delete-mfa-authenticator.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/delete-push-target.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/delete-session.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/delete-sessions.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/get-mfa-recovery-codes.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/get-prefs.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/get-session.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/get.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/list-identities.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/list-logs.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/list-mfa-factors.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/list-sessions.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/update-email.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/update-m-f-a.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/update-magic-u-r-l-session.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/update-mfa-authenticator.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/update-mfa-challenge.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/update-mfa-recovery-codes.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/update-name.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/update-password.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/update-phone-session.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/update-phone-verification.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/update-phone.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/update-prefs.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/update-push-target.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/update-recovery.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/update-session.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/update-status.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/account/update-verification.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/avatars/get-browser.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/avatars/get-credit-card.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/avatars/get-favicon.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/avatars/get-flag.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/avatars/get-image.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/avatars/get-initials.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/avatars/get-q-r.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/databases/create-document.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/databases/delete-document.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/databases/get-document.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/databases/list-documents.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/databases/update-document.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/functions/create-execution.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/functions/get-execution.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/functions/list-executions.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-android/kotlin/graphql/mutation.md is excluded by !docs/examples/**
📒 Files selected for processing (63)
  • .coderabbit.yaml (1 hunks)
  • .env (2 hunks)
  • .github/workflows/benchmark.yml (1 hunks)
  • .github/workflows/cleanup-cache.yml (1 hunks)
  • .github/workflows/codeql-analysis.yml (1 hunks)
  • .github/workflows/linter.yml (1 hunks)
  • .github/workflows/publish.yml (1 hunks)
  • .github/workflows/release.yml (1 hunks)
  • .github/workflows/static-analysis.yml (1 hunks)
  • .github/workflows/tests.yml (8 hunks)
  • .gitignore (1 hunks)
  • CONTRIBUTING.md (1 hunks)
  • Dockerfile (2 hunks)
  • README-CN.md (3 hunks)
  • README.md (3 hunks)
  • app/cli.php (5 hunks)
  • app/config/collections/common.php (3 hunks)
  • app/config/collections/platform.php (13 hunks)
  • app/config/collections/projects.php (21 hunks)
  • app/config/errors.php (9 hunks)
  • app/config/events.php (1 hunks)
  • app/config/frameworks.php (1 hunks)
  • app/config/locale/templates/email-base-styled.tpl (6 hunks)
  • app/config/oAuthProviders.php (42 hunks)
  • app/config/platforms.php (16 hunks)
  • app/config/roles.php (3 hunks)
  • app/config/runtimes.php (1 hunks)
  • app/config/scopes.php (2 hunks)
  • app/config/services.php (1 hunks)
  • app/config/specifications.php (1 hunks)
  • app/config/storage/inputs.php (0 hunks)
  • app/config/storage/outputs.php (0 hunks)
  • app/config/template-runtimes.php (1 hunks)
  • app/config/templates/function.php (78 hunks)
  • app/config/templates/site.php (1 hunks)
  • app/config/variables.php (9 hunks)
  • app/controllers/api/account.php (16 hunks)
  • app/controllers/api/avatars.php (5 hunks)
  • app/controllers/api/console.php (3 hunks)
  • app/controllers/api/health.php (1 hunks)
  • app/controllers/api/migrations.php (3 hunks)
  • app/controllers/api/project.php (10 hunks)
  • app/controllers/api/projects.php (2 hunks)
  • app/controllers/api/proxy.php (3 hunks)
  • app/controllers/api/storage.php (10 hunks)
  • app/controllers/api/teams.php (4 hunks)
  • app/controllers/api/users.php (5 hunks)
  • app/controllers/api/vcs.php (17 hunks)
  • app/controllers/general.php (33 hunks)
  • app/controllers/shared/api.php (14 hunks)
  • app/http.php (6 hunks)
  • app/init/configs.php (3 hunks)
  • app/init/constants.php (8 hunks)
  • app/init/database/filters.php (2 hunks)
  • app/init/registers.php (2 hunks)
  • app/init/resources.php (8 hunks)
  • app/views/general/404.phtml (1 hunks)
  • app/views/general/error.phtml (2 hunks)
  • app/views/install/compose.phtml (15 hunks)
  • app/worker.php (5 hunks)
  • bin/screenshot (1 hunks)
  • composer.json (6 hunks)
  • docker-compose.yml (17 hunks)
💤 Files with no reviewable changes (2)
  • app/config/storage/inputs.php
  • app/config/storage/outputs.php
🧰 Additional context used
🧬 Code Graph Analysis (5)
app/config/errors.php (1)
src/Appwrite/Extend/Exception.php (1)
  • Exception (7-406)
app/controllers/api/account.php (2)
src/Appwrite/GraphQL/Types/Mapper.php (1)
  • param (253-349)
src/Appwrite/Vcs/Comment.php (1)
  • isEmpty (26-29)
app/init/resources.php (3)
src/Appwrite/Utopia/Request.php (2)
  • Request (13-236)
  • getHeader (195-199)
src/Appwrite/Auth/Key.php (3)
  • Key (13-200)
  • getHostnameOverride (67-70)
  • decode (102-199)
src/Appwrite/Extend/Exception.php (1)
  • Exception (7-406)
app/init/constants.php (1)
src/Appwrite/Platform/Appwrite.php (1)
  • Appwrite (14-26)
app/controllers/api/storage.php (4)
src/Appwrite/GraphQL/Types/Mapper.php (1)
  • param (253-349)
src/Appwrite/Utopia/Response.php (3)
  • output (658-740)
  • Response (135-905)
  • file (751-758)
src/Appwrite/Extend/Exception.php (1)
  • Exception (7-406)
src/Appwrite/Utopia/Request.php (1)
  • Request (13-236)
🪛 YAMLlint (1.37.1)
.coderabbit.yaml

[error] 11-11: no new line character at the end of file

(new-line-at-end-of-file)

.github/workflows/static-analysis.yml

[error] 16-16: no new line character at the end of file

(new-line-at-end-of-file)

.github/workflows/tests.yml

[error] 125-125: trailing spaces

(trailing-spaces)


[error] 276-276: trailing spaces

(trailing-spaces)

🪛 LanguageTool
CONTRIBUTING.md

[uncategorized] ~168-~168: You might be missing the article “the” here.
Context: ... Modules As Appwrite grows, we noticed approach of having all service endpoints in `app...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~168-~168: This verb does not appear to agree with the subject. Consider using a different form.
Context: ...].php` is not maintainable. Not only it creates massive files, it also doesnt contain a...

(AI_EN_LECTOR_REPLACEMENT_VERB_AGREEMENT)


[uncategorized] ~168-~168: You might be missing the article “the” here.
Context: ...ssive files, it also doesnt contain all product's features such as workers or tasks. Wh...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~172-~172: You might be missing the article “the” here.
Context: ... Endpoints Every endpoint file follows below structure, making it consistent with HT...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~180-~180: You might be missing the article “the” here.
Context: ...ction].php ``` Tips and tricks: 1. If endpoint doesn't have resource, use service name...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~180-~180: You might be missing the article “a” here.
Context: ...sn't have resource, use service name as resource name too > Example: `Modules/Sites/Http...

(AI_EN_LECTOR_MISSING_DETERMINER_A)

🪛 markdownlint-cli2 (0.17.2)
CONTRIBUTING.md

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

(MD040, fenced-code-language)

🪛 actionlint (1.7.7)
.github/workflows/tests.yml

306-306: property "tables-mode" is not defined in object type {}

(expression)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: E2E Shared Mode Service Test (Realtime, Shared V2)
  • GitHub Check: E2E Shared Mode Service Test (Teams, Shared V2)
🔇 Additional comments (93)
.coderabbit.yaml (2)

2-6: Path filters look correct.
The glob patterns correctly exclude generated specs and docs directories from reviews, focusing attention on source code changes.


8-11: Verify target branches for auto-review.
You’ve included 1.6.x and 1.7.x alongside main as base branches. Since this PR is intended to be retargeted to main before merge, please confirm whether those legacy branches should remain or be pruned.

🧰 Tools
🪛 YAMLlint (1.37.1)

[error] 11-11: no new line character at the end of file

(new-line-at-end-of-file)

.github/workflows/release.yml (1)

14-14: Upgrade actions/checkout to v4 is appropriate.
Aligns with other workflows and ensures compatibility with the latest features and performance improvements.

.github/workflows/cleanup-cache.yml (1)

13-13: Upgrade actions/checkout to v4 is consistent.
Standardizes the checkout step across all CI workflows. No logic changes required.

app/config/specifications.php (1)

3-3: Namespace import updated correctly.
Switching to Appwrite\Platform\Modules\Compute\Specification aligns with the new modular architecture.

README-CN.md (1)

75-75: Bumped Docker image tag to 1.7.0.
The updated version in all three code blocks matches the new release. No additional examples appear to require updating.

Also applies to: 87-87, 97-97

README.md (3)

81-81: Approve version bump for Unix install command
The Docker image tag has been correctly updated to appwrite/appwrite:1.7.0.
Please verify that the 1.7.0 image is published and available on Docker Hub.


93-93: Approve version bump for Windows CMD install
The appwrite/appwrite image version has been updated to 1.7.0, matching the Unix command above.


103-103: Approve version bump for Windows PowerShell install
Consistent update of the image tag to 1.7.0. Good to go.

app/config/runtimes.php (1)

9-9: Approve runtime version upgrade to v5
The Runtimes constructor argument has been updated from 'v4' to 'v5', aligning with executor changes.
Ensure that the Runtimes class and all downstream logic fully support the new 'v5' environment.

.github/workflows/codeql-analysis.yml (1)

37-37: Approve checkout action upgrade to v4
Updated actions/checkout@v3 to @v4 for consistency across CI workflows.

.gitignore (1)

6-6: Approve ignore rule for site archive files
Added /tests/resources/sites/**/code.tar.gz to prevent committed build artifacts for sites.

.github/workflows/publish.yml (1)

15-15: Approve checkout action upgrade to v4
Aligned with other workflows by bumping actions/checkout to version 4.

.github/workflows/linter.yml (1)

15-15: Upgrade actions/checkout to v4
The workflow now uses actions/checkout@v4, aligning with other CI updates in this PR. Ensure there are no regressions related to shallow cloning or caching.

app/init/registers.php (1)

18-18: Import Utopia\Database\PDO added
Good catch—adding this import ensures that new PDO(...) refers to the Utopia adapter rather than the global \PDO class.

Dockerfile (2)

47-55: Add /storage/imports directory with proper permissions
The new imports storage directory is created and its ownership/permissions match existing storage paths. Ensure the corresponding volume is mapped in your docker-compose.yml.


73-73: Grant execute permission for the screenshot script
Adding execute rights for /usr/local/bin/screenshot is necessary to support the new wrapper script.

app/config/oAuthProviders.php (1)

14-464: Standardize OAuth provider class resolution
The addition of the 'class' key for each OAuth provider centralizes the fully qualified class names and decouples provider logic from hardcoded namespaces. Confirm that all controllers now retrieve the provider class from this configuration and that providers commented out or missing a 'class' entry are handled gracefully.

app/init/database/filters.php (2)

136-148: Well-structured new database filter for development keys

The new subQueryDevKeys filter follows the established pattern of other subquery filters in the file and correctly implements the necessary queries to fetch development keys associated with a project.


242-242: Appropriate extension of resource types to include sites

The modification to include 'site' alongside 'function' in the resourceType condition correctly supports the expansion of resource types in the platform.

app/config/locale/templates/email-base-styled.tpl (4)

82-82: Good parameterization of button styling

Replacing hardcoded colors with the dynamic {{accentColor}} variable enables consistent branding across emails that can be configured at runtime.

Also applies to: 91-91


129-129: Appropriately parameterized logo URL

Using {{logoUrl}} instead of a hardcoded path allows for dynamic logo configuration in emails.


167-167: Well-implemented social media link parameterization

The social media links are now properly templated using variables for Twitter, Discord, and GitHub URLs, allowing for easier configuration and maintenance.

Also applies to: 176-176, 184-184


194-194: Improved footer link configurability

The Terms and Privacy links are now parameterized with {{termsUrl}} and {{privacyUrl}}, supporting custom landing pages per installation.

Also applies to: 198-198

app/config/template-runtimes.php (1)

6-43:

Details

❓ Verification inconclusive

Comprehensive runtime version configuration

The runtime configuration provides a well-structured mapping of runtime environments to their supported versions. This supports both function templates and site frameworks as noted in the comments.

Run the following to verify that the runtime versions listed are consistent with what's supported in the runtime services:


🏁 Script executed:

#!/bin/bash
# Check if these runtime configs match the actual runtimes.php file
cat app/config/runtimes.php | grep -A 5 "versions"

Length of output: 50


🏁 Script executed:

#!/bin/bash
# Verify the runtime versions block in the correct file
grep -n "versions" app/config/template-runtimes.php -A5

Length of output: 1055


Verify runtime version mappings in template-runtimes.php

I’ve confirmed that the versions arrays in app/config/template-runtimes.php (lines 9–41) match the submitted snippet. Before merging, please cross-check each runtime’s version list against your official supported-runtimes source to ensure they’re up to date.

• File: app/config/template-runtimes.php (lines 9–41)

app/config/roles.php (2)

29-29: Permission scope addition to member role

Adding the rules.read permission to the member role is appropriate for allowing users to read rule configurations.


62-65: Additional permissions for admin role reflect new platform features

The new permissions for sites, logs, and tokens properly expand the admin role capabilities to support the new features being introduced in the platform.

I see these changes align with the introduction of the sites service and token management features mentioned in the PR summary.

Also applies to: 84-85

app/init/configs.php (3)

5-5: Config loading order adjustment introduces template-runtimes config

This adds a new configuration file for template runtimes at the beginning of the loading sequence, which is consistent with the expanded site support features introduced in this update.


14-14: New frameworks configuration added

Adding the frameworks configuration expands the platform's capability to support different web frameworks for both function and site deployments.


38-40: Reorganized configuration loading for specifications and templates

These changes consolidate what were likely separate configuration files into a more structured approach, separating function and site templates while maintaining a unified specifications file. This reorganization aligns with the new site hosting capabilities.

app/controllers/api/health.php (1)

848-848: Extended health checks to include sites storage device

The health storage endpoint now properly includes the new sites storage device in its health checks, ensuring comprehensive coverage of all storage components. This is a necessary addition given the new sites functionality being introduced.

Also applies to: 850-851

app/config/platforms.php (1)

14-14:

Details

❓ Verification inconclusive

Updated SDK versions across all platforms

All SDK versions have been incremented to support the new platform capabilities, particularly the sites functionality. This coordinated version bump ensures consistent API support across all client, console, and server SDKs.

Let's check if the version increments are aligned with semantic versioning principles based on the magnitude of changes:

Also applies to: 62-62, 80-80, 115-115, 137-137, 202-202, 248-248, 266-266, 284-284, 302-302, 320-320, 338-338, 356-356, 374-374, 392-392, 414-414


🌐 Web query:

What changes are typically included in major version updates for SDKs in terms of backward compatibility?

💡 Result:

Major version updates for SDKs typically introduce backward incompatible changes that require developers to modify their existing code. These updates represent significant shifts in the SDK's functionality and structure.

Breaking Changes in Major Version Updates

Major version updates (changing the X in X.Y.Z semantic versioning) indicate substantial modifications that aren't backward compatible with previous versions. These changes often require careful consideration before upgrading.

API Incompatibilities
Major updates frequently include incompatible API changes such as:

  • Removing or renaming functions, methods, or classes[9]
  • Changing parameter types or return values[5]
  • Adding required parameters to existing methods[5]
  • Altering the behavior of existing functionality in ways that could break dependent code[1]

Structural Changes
Major versions may also introduce:

  • New product directions or significant architectural modifications[3]
  • Changes to underlying dependencies or requirements[8]
  • Complete refactoring to support new idioms and patterns in the programming language[8]

Support Implications
When a major version is released:

  • All version numbers are typically reset (e.g., from 2.0.4 to 3.0.0)[6]
  • Previously stable APIs may be removed entirely if they were appropriately deprecated in earlier versions[7]
  • New features and bug fixes are generally only released for the latest major version, encouraging migration[5]

Impact on Developers

Major version updates require careful planning because they:

  • Force developers to modify their existing code to maintain compatibility[5]
  • May prevent downgrading to previous versions once adopted[10]
  • Could require significant testing to ensure application stability after migration[1]

SDK providers typically maintain clear documentation about these breaking changes and often provide migration guides to help developers transition between major versions. For many enterprise applications, it's considered best practice to thoroughly test major version updates in staging environments before deploying to production[1].

Citations:


Validate Major Version Bump for SDKs

Please confirm that the jump to 18.0.0 (and the corresponding bumps at lines 62, 80, 115, 137, 202, 248, 266, 284, 302, 320, 338, 356, 374, 392, and 414) truly introduces breaking changes in line with semantic-versioning rules. Major version updates must reflect backward-incompatible API or structural changes.

• Review each SDK’s changelog or migration guide to identify and document any removed/renamed methods, altered behaviors, changed parameters, or architectural shifts in 18.0.0.
• Ensure all dependent code (client, console, server) has been updated to accommodate these changes.
• Update your release notes or add a migration section in documentation to clearly list these breaking changes and provide upgrade instructions.

app/config/services.php (1)

178-183: Double-check controller routing for empty string

Both the new sites and the updated functions entries set 'controller' => '' with the comment “Uses modules”.
Please verify that:

  1. The HTTP router treats an empty string as “module handled” and does not try to load a PHP file.
  2. No older code paths still expect a non-empty path (e.g. for CLI tooling or Swagger generation).

If any call sites still assume a file path, runtime errors will surface only at request time.

app/cli.php (2)

31-35: Runtime version hard-coded to v5

new Runtimes('v5') assumes that every deployment already ships runtime definitions for v5. If someone back-ports this branch onto an environment that only has up to v4, tasks will fatal at bootstrap.

Gracefully fall back, e.g.:

$version = Config::getParam('_APP_RUNTIME_VERSION', 'v5');
Config::setParam('runtimes', (new Runtimes($version))->getAll(supported: false));

Or catch InvalidArgumentException from Runtimes.


296-299: Timer cleanup outside coroutine context

Timer::clearAll() is called both inside the error handler and in a shutdown hook. That’s good, but remember that if the run() wrapper is fixed to execute inside a coroutine, the shutdown callback must still run inside the same context or you’ll see “Timer::clearAll(): no reactor” notices when the event loop has already exited.

Keep an eye on this once the coroutine wrapper is corrected.

app/config/scopes.php (3)

67-72: Addition of site-related access scopes aligns with new static site functionality.

The new sites.read and sites.write scopes properly follow Appwrite's established permissions pattern for granular control over the new sites feature. This maintains consistency with the existing permission structure.


73-78: Log access scopes provide proper granular permissions for site logs.

The addition of log.read and log.write scopes creates a clear separation of concerns for accessing and managing site logs, consistent with Appwrite's permission architecture.


145-150: Token management scopes appropriately established.

The tokens.read and tokens.write scopes correctly implement the permission structure needed for the new token management functionality, maintaining consistency with other resource types.

app/config/templates/function.php (3)

3-5: Good refactoring to use dynamic runtime configuration.

Replacing hardcoded runtimes with dynamic configuration from Config::getParam('template-runtimes') improves maintainability and centralization of runtime definitions, making it easier to add or modify runtime environments without code changes.


26-26: Template scoring system enhances template selection.

The addition of the score attribute to function templates implements a numerical ranking system that facilitates better template organization and prioritization. This will improve template discovery and selection in the UI.

Also applies to: 111-111, 155-155, 207-207, 245-245, 314-314, 376-376, 440-440, 525-525, 592-592, 676-676, 725-725, 773-773, 820-820, 908-908, 965-965, 1047-1047, 1090-1090, 1148-1148, 1218-1218, 1276-1276, 1336-1336, 1395-1395, 1454-1454, 1532-1532, 1574-1574, 1611-1611, 1674-1674, 1739-1739, 1795-1795, 1837-1837, 1879-1879, 1921-1921, 1958-1958, 2014-2014


35-53: Runtime references properly updated to use dynamic configuration.

The change to use $templateRuntimes instead of hardcoded constants throughout the file ensures consistency and centralizes runtime management. This is a positive architectural improvement.

composer.json (3)

18-18: Static analysis integration through PHPStan.

The addition of the check script command provides a standardized way to run static analysis, which will help maintain code quality and catch potential issues earlier in development.


92-92: PHPStan addition enables static code analysis.

Adding PHPStan as a development dependency is a good practice for implementing static code analysis, which can help identify potential bugs, type errors, and other issues before they reach production.


105-107: Plugin configuration updated for new dependencies.

The allow-plugins configuration has been updated to enable php-http/discovery and tbachert/spi plugins, which are likely required by the updated dependencies.

app/controllers/api/projects.php (2)

2142-2143: Dependency Injection Improvement

The code now injects a plan array as a dependency in the SMTP test email endpoint, enhancing the function signature to make branding and configuration more flexible.


2156-2163: Enhanced Email Template Customization

The code now uses the injected plan configuration to dynamically populate email template parameters, with fallbacks to global constants. This allows for customizable branding and legal/social links in test emails.

This is a good implementation of the template parameter system that maintains backward compatibility through fallback values while enabling customization.

app/http.php (5)

16-16: Added Compression Import

Added the Compression class import which is used for the new screenshots bucket configuration.


32-32: Static File Loading Enhancement

Added static file loading from the public directory at startup, which enables efficient serving of static assets.


314-360: New Screenshots Bucket Implementation

Added a dedicated screenshots bucket with specific configurations tailored for image storage, including size limits, format restrictions, and optimization settings.

The code creates a specialized bucket for screenshots with these key features:

  • 20MB file size limit
  • PNG format restriction for consistency and security
  • Gzip compression enabled for storage efficiency
  • Authorization.skip() used appropriately to perform system-level operations
  • Reuses existing file collection configuration for consistency

This implementation aligns with the platform's evolution to support new resource types while maintaining security and performance considerations.


549-549: Updated Event Constant Usage

The code now uses the standardized Constant::EVENT_TASK instead of a string literal, improving maintainability.


583-584: Enhanced Domain Filtering Logic

Updated domain filtering to exclude domains ending with either functions domain or sites domain environment variables, supporting the expanded platform features.

This change accommodates the new "sites" functionality being added to the platform, ensuring proper domain routing and security checks for both functions and sites resources.

app/controllers/api/migrations.php (1)

309-432: New endpoint for CSV migrations integrates well with existing patterns

This implementation adds a new endpoint for importing documents from CSV files as a migration source. The code follows the established patterns from other migration types and includes proper authorization, file processing, and queuing mechanics.

I noticed that unlike other migration endpoints (lines 96-98), the CSV migration doesn't set the user when triggering the migration (lines 424-427). Was this omission intentional?

$queueForMigrations
    ->setMigration($migration)
    ->setProject($project)
+   ->setUser($user)
    ->trigger();
app/controllers/api/avatars.php (5)

190-190: Parameter default change affects quality handling behavior

The default value for the quality parameter has been changed from 100 to -1, with the description updated to indicate it will "keep existing image quality" rather than use maximum quality.

This change in default behavior might affect existing clients. Please confirm that this change is compatible with all client implementations and update documentation accordingly.


218-218: Consistent quality parameter change for browser icons

This change mirrors the quality parameter change in the credit card endpoint.


246-246: Consistent quality parameter change for flag icons

This change mirrors the quality parameter changes in other avatar endpoints.


505-506: QR code scale addition improves readability

Adding a scale option to the QR code generation will produce larger QR code patterns within the image.


520-520: Substantial QR code quality improvement

The PNG output quality for QR codes has been significantly increased from the default (likely 9) to 90.

This will result in much higher quality QR code images, though with larger file sizes. The change makes sense for ensuring QR codes are readable in all scenarios.

app/controllers/api/console.php (2)

46-60: Enhanced domain validation improves security and reliability

The previous simple validation has been replaced with more robust validation using Domain and IP validators. The new implementation properly checks for known non-test domains and validates IPv4/IPv6 addresses.

The domain is now considered enabled when:

  1. _APP_DOMAIN is a valid, known, non-test domain, AND
  2. At least one of the target records (CNAME, A, or AAAA) is valid

This provides more flexibility while maintaining security standards.


71-83: Environment variable structure updated for broader architecture support

The response structure has been updated to reflect architectural changes in the platform:

  1. _APP_DOMAIN_TARGET has been replaced by separate CNAME, A, and AAAA record variables
  2. _APP_FUNCTIONS_SIZE_LIMIT renamed to _APP_COMPUTE_SIZE_LIMIT
  3. New variables added for sites, functions domains, and HTTPS options

This change suggests a shift from function-specific architecture to a broader compute model that also supports sites, aligning with the AI summary's mention of "support for sites alongside functions."

app/controllers/api/teams.php (2)

322-327: requestTimestamp is now injected but never used
requestTimestamp is still injected (line 310) but the new implementation removed the withRequestTimestamp() wrapper and simply calls:

$team = $dbForProject->updateDocument('teams', $team->getId(), $team);

Any optimistic-locking or concurrency protection that relied on the original timestamp is now bypassed. Please verify that this change is intentional; otherwise, stale writes could silently overwrite newer data.


1091-1105: Efficient owner-count query – looks good
Scoping the roles query with teamInternalId (lines 1093-1096) prevents miscounting owners across organisations. Nice catch and minimal performance impact with the hard max: 2 limit.

app/worker.php (2)

369-371: plan resource returns an empty array – double-check downstream expectations
Several controllers inject plan and immediately index into it ($plan['authPhone'], etc.). Returning [] will raise Undefined index notices in PHP 8.2+. If the intention is “no plan”, consider returning a typed Document with sensible defaults or at least:

return ['features' => [], 'limits' => []];

383-406: Null-safe iteration on $extras – nice improvement
Wrapping the foreach with ($extras ?? []) prevents TypeError when nothing is supplied.

app/config/events.php (1)

220-247: Good addition of the new sites event category.

The new event structure follows the same pattern as existing resources like functions, with proper model references, resource flags, and standardized event triggers (create, delete, update). This addition properly integrates sites as a first-class resource within the event system.

app/controllers/api/project.php (4)

20-20: LGTM: Added Boolean validator import.

This import is needed for the new secret parameter in variable endpoints.


153-153: Good refactoring to generalize metrics for multiple resource types.

The code now uses separate {resourceType} and {resourceInternalId} placeholders instead of function-specific placeholders. This change supports the platform's expansion to handle multiple resource types (functions and sites) in a unified way.

Also applies to: 169-169, 185-185, 234-235, 240-241, 258-259, 274-275


405-405: Good addition of secret flag for project variables.

Adding the secret flag enhances security by allowing variables to be marked as sensitive, which can limit their visibility during build and runtime.

Also applies to: 410-410, 425-425


529-529: Good security enhancement preventing secret variables from being downgraded.

The code now prevents variables marked as secret from having their secret flag unset, which is an important security protection.

Also applies to: 534-534, 540-542, 547-547

app/controllers/api/users.php (4)

12-13: LGTM: Added delete helper classes imports.

These imports support the enhanced cleanup operations when deleting users.


26-26: LGTM: Added Memberships query validator import.

Required for the enhanced filtering capability in the membership listing endpoint.


826-827: Good enhancement to membership listing with filtering and search.

The endpoint now supports advanced filtering and search capabilities for user memberships, which improves API flexibility and usability.

Also applies to: 838-850


2296-2297: Thorough cleanup on user deletion.

The code now properly deletes all associated identities and targets when a user is deleted, preventing orphaned records in the database.

app/config/collections/common.php (2)

1443-1448: Indexing an array column (roles) with INDEX_KEY may not behave as expected

roles is stored as an array – ultimately a JSON string – so the new _key_roles BTREE index will only be useful for exact value matches on the entire encoded string.
If the goal is to query for memberships that contain a role (e.g. member, owner) consider:

  • Keeping the column scalar and creating a join table or
  • Switching the index to INDEX_FULLTEXT and using full-text search predicates.

Otherwise the index adds write-overhead without real query benefit.


2385-2397: Good addition – indexes for expired & sessionInternalId

These two keys are frequently filtered in house-keeping and look-up paths; the new indexes will reduce full-table scans.

app/controllers/api/account.php (9)

722-722: Database operation simplification

The code now directly calls the deleteDocument method without using a withRequestTimestamp wrapper. This simplification appears throughout the file for database operations and makes the code more straightforward.


1185-1186: Enhanced URL validation with development key support

The validator now intelligently adapts based on the presence of a development key, using a more strict Host validator when no dev key is present and a more permissive URL validator otherwise. This change improves security while providing flexibility for development scenarios.


1213-1214: Improved OAuth2 provider resolution

The code now retrieves OAuth2 provider class names from configuration instead of using hardcoded namespace concatenation. This change enhances modularity and makes the OAuth2 provider system more configurable.

- $className = 'Appwrite\\Auth\\OAuth2\\' . \ucfirst($provider);
+ $oAuthProviders = Config::getParam('oAuthProviders');
+ $className = $oAuthProviders[$provider]['class'];

1782-1783: Consistent implementation of development key support for OAuth2 token URL validation

Similar to the changes in the OAuth2 session endpoint, this update implements the same flexible validation pattern for success and failure URLs in the OAuth2 token creation endpoint.


1863-1863: Development key support for magic URL login redirection

The magic URL login endpoint now also implements the dynamic validator selection pattern based on development key presence, consistent with other authentication endpoints.


2002-2003: Minor whitespace adjustment

Small whitespace change for better code readability.


2771-2771: Simplified database update operations

Multiple instances of database update operations have been simplified by removing the withRequestTimestamp wrapper, making the code more consistent and easier to understand. The updated code now directly assigns the result of the update operation back to the user variable, which allows for proper handling of the returned updated document.

Also applies to: 2846-2846, 2931-2931, 3017-3017, 3067-3067, 3105-3105, 3869-3869


3149-3149: Development key support for password recovery URL validation

The password recovery endpoint now implements the same flexible URL validation based on development key presence, consistent with other authentication endpoints.


3415-3415: Development key support for email verification URL validation

The email verification endpoint now also implements the development key-based URL validation, providing consistent behavior across all authentication-related endpoints that use URL redirection.

.github/workflows/benchmark.yml (1)

71-79: Security & reproducibility – pin the production compose/env files
Fetching docker-compose.yml and .env from the live site means every CI run may pick up different images or configs, breaking reproducibility and obscuring regressions.

Consider referencing a specific release tag (or commit hash) instead of latest:

-          curl https://appwrite.io/install/compose -o docker-compose.yml
-          curl https://appwrite.io/install/env -o .env
+          curl -sL https://raw.githubusercontent.com/appwrite/appwrite/1.6.2/docker-compose.yml -o docker-compose.yml
+          curl -sL https://raw.githubusercontent.com/appwrite/appwrite/1.6.2/.env -o .env

This locks the baseline for fair, deterministic comparisons.

app/views/general/error.phtml (1)

56-58: Inconsistent size-class naming (large-error ↔︎ small-error)
$isSimpleMessage = true maps to large-error, while complex messages map to small-error, which is counter-intuitive.
If this is accidental, swap the class names for clarity; otherwise consider renaming the boolean for readability.

.env (1)

76-84: Verify naming consistency between “Functions” and new “Compute” vars

You introduce _APP_COMPUTE_* limits (size, build timeout, CPU, memory …) yet _APP_FUNCTIONS_TIMEOUT remains the old name for per-function timeout.
If functions are now part of “Compute”, consider either:

  1. Adding an _APP_COMPUTE_TIMEOUT and deprecating _APP_FUNCTIONS_TIMEOUT, or
  2. Documenting that functions still read the legacy variable while sites use _APP_SITES_TIMEOUT.

Please double-check runtime code paths to avoid a mismatch in timeout enforcement.

app/controllers/api/storage.php (1)

410-413: SDK metadata looks correct – nice addition of explicit UPLOAD semantics

Setting

type: MethodType::UPLOAD,
requestType: ContentType::MULTIPART

makes the behaviour unambiguous for code-generators and clients; 👍 for tightening the contract.

app/init/resources.php (1)

934-958: Constant safety check

TOKENS_RESOURCE_TYPE_FILES is referenced without a use or define.
If the constant isn’t defined it will throw an Error on PHP 8+.
Consider importing or adding an explicit defined() guard.

docker-compose.yml (1)

975-978: Verify that _APP_DOMAIN_SITES is defined

_APP_DOMAIN_SITES is passed to multiple services but isn’t present in app/config/variables.php.
Please confirm it is defined elsewhere; otherwise the variable will be empty inside the containers.

app/init/constants.php (1)

76-79:

Details

✅ Verification successful

Rename ripple check: do we still reference the old _APP_FUNCTION_* constants anywhere?

The defaults were renamed to APP_COMPUTE_*, but residual usages of APP_FUNCTION_CPUS_DEFAULT / APP_FUNCTION_MEMORY_DEFAULT will now be undefined and evaluated as null.


🏁 Script executed:

#!/bin/bash
# Find references to the old constants that would now break.
rg --fixed-strings --type php 'APP_FUNCTION_CPUS_DEFAULT|APP_FUNCTION_MEMORY_DEFAULT'

Length of output: 87


No leftover references to APP_FUNCTION_* constants
Ran a global search across the PHP codebase and found no usages of APP_FUNCTION_CPUS_DEFAULT or APP_FUNCTION_MEMORY_DEFAULT. The rename to the new APP_COMPUTE_* constants is safe to merge.

app/config/collections/platform.php (1)

228-234:

Details

❌ Incorrect review comment

Re-evaluate 1 000 000-byte column size & fix TODO

templates jumps from 16 384 to 1 000 000 bytes with a // TODO make sure size fits note.
• MySQL TEXT is limited to 65 535 B – 1 000 000 silently promotes to MEDIUMTEXT (16 MiB).
• On PostgreSQL the declaration maps to TEXT, so the value is ignored.
Relying on implicit type‐upgrades is risky and platform-specific.

-    'size' => 1_000_000, // TODO make sure size fits
+    // MEDIUMTEXT upper-bound (16 777 215). Set explicit constant to avoid silent type change.
+    'size' => Database::LENGTH_MEDIUMTEXT,

Remove the TODO once verified.

Would you like a quick shell script that checks the current driver’s max length mapping?


🏁 Script executed:

#!/usr/bin/env bash
set -e

# Locate the Database class file
db_file=$(rg -l "class Database" . | head -n1)

if [[ -n "$db_file" ]]; then
  echo "🔍 Found Database class in: $db_file"
  echo "📝 Listing LENGTH_* constants defined in Database:"
  rg "const LENGTH_" -n "$db_file"
else
  echo "❗️ Database class definition not found in repository."
fi

echo
echo "🔍 Searching for any usage of LENGTH_MEDIUMTEXT:"
rg "LENGTH_MEDIUMTEXT" -n .

Length of output: 574


🏁 Script executed:

#!/usr/bin/env bash
set -e

echo "🔍 Searching for PHP files defining class Database (excluding tests)…"
rg -n --glob "!tests/*" "class Database" .

echo
echo "🔍 Searching for LENGTH_MEDIUMTEXT constant definitions…"
rg -n "const LENGTH_MEDIUMTEXT" --glob "*.php"

Length of output: 956


Verify template JSON maximum size and remove TODO

The templates field jumps from 16 384 bytes straight to 1 000 000 bytes, exceeding MySQL’s TEXT limit (65 535 B → implicit MEDIUMTEXT) and being ignored on PostgreSQL (TEXT is unbounded).

Action items:

  • Confirm that 1 000 000 bytes is the desired upper bound.
  • Remove the // TODO make sure size fits comment once confirmed.
  • To avoid a magic number, define a descriptive constant (for example, TEMPLATES_MAX_SIZE = 1_000_000) rather than referencing a non-existent Database::LENGTH_MEDIUMTEXT.

File to update:

  • app/config/collections/platform.php (around line 228)

Likely an incorrect or invalid review comment.

app/controllers/general.php (1)

1050-1053: Origin validation bypassed for dev-key – document intent

&& $devKey->isEmpty() bypasses the CSRF origin validator when any dev-key is present. If this is intentional (e.g., internal tooling), add an inline comment explaining the security model; otherwise reconsider.

app/config/collections/projects.php (1)

1183-1192: Constant APP_COMPUTE_SPECIFICATION_DEFAULT must be defined

The default value for the specification attribute references APP_COMPUTE_SPECIFICATION_DEFAULT.
Compilation will fail if the constant is missing or renamed.

Please verify the constant exists in app/init/constants.php.

Also applies to: 1675-1684

Comment on lines +217 to 231
$validators = [];
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', ''));
if (!$targetCNAME->isKnown() || $targetCNAME->isTest()) {
$validators[] = new DNS($targetCNAME->get(), DNS::RECORD_CNAME);
}
if ((new IP(IP::V4))->isValid(System::getEnv('_APP_DOMAIN_TARGET_A', ''))) {
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_A', ''), DNS::RECORD_A);
}
if ((new IP(IP::V6))->isValid(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''))) {
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), DNS::RECORD_AAAA);
}

if (!$target->isKnown() || $target->isTest()) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Domain target must be configured as environment variable.');
if (empty($validators)) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'At least one of domain targets environment variable must be configured.');
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Potential mis-validation when _APP_DOMAIN_TARGET_CNAME is empty

$targetCNAME is always instantiated – even when the env-var is an empty string.
Because an empty string is neither known nor test, the if condition becomes true and a DNS validator gets created with an empty host name.
This will fail every verification attempt and may even hide the real reason from the caller.

- $targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', ''));
- if (!$targetCNAME->isKnown() || $targetCNAME->isTest()) {
-     $validators[] = new DNS($targetCNAME->get(), DNS::RECORD_CNAME);
- }
+ $targetCNAMEEnv = System::getEnv('_APP_DOMAIN_TARGET_CNAME', '');
+ if (!empty($targetCNAMEEnv)) {
+     $targetCNAME = new Domain($targetCNAMEEnv);
+     // Skip validation for local/test domains, but validate all real domains.
+     if (!$targetCNAME->isTest()) {
+         $validators[] = new DNS($targetCNAME->get(), DNS::RECORD_CNAME);
+     }
+ }

Side effects:

  1. Prevents unnecessary look-ups when the variable is not configured.
  2. Keeps the “at least one validator” logic intact while avoiding false negatives.
📝 Committable suggestion

‼️ 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.

Suggested change
$validators = [];
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', ''));
if (!$targetCNAME->isKnown() || $targetCNAME->isTest()) {
$validators[] = new DNS($targetCNAME->get(), DNS::RECORD_CNAME);
}
if ((new IP(IP::V4))->isValid(System::getEnv('_APP_DOMAIN_TARGET_A', ''))) {
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_A', ''), DNS::RECORD_A);
}
if ((new IP(IP::V6))->isValid(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''))) {
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), DNS::RECORD_AAAA);
}
if (!$target->isKnown() || $target->isTest()) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Domain target must be configured as environment variable.');
if (empty($validators)) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'At least one of domain targets environment variable must be configured.');
}
$validators = [];
$targetCNAMEEnv = System::getEnv('_APP_DOMAIN_TARGET_CNAME', '');
if (!empty($targetCNAMEEnv)) {
$targetCNAME = new Domain($targetCNAMEEnv);
// Skip validation for local/test domains, but validate all real domains.
if (!$targetCNAME->isTest()) {
$validators[] = new DNS($targetCNAME->get(), DNS::RECORD_CNAME);
}
}
if ((new IP(IP::V4))->isValid(System::getEnv('_APP_DOMAIN_TARGET_A', ''))) {
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_A', ''), DNS::RECORD_A);
}
if ((new IP(IP::V6))->isValid(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''))) {
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), DNS::RECORD_AAAA);
}
if (empty($validators)) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'At least one of domain targets environment variable must be configured.');
}
🤖 Prompt for AI Agents
In app/controllers/api/proxy.php around lines 217 to 231, the code creates a
Domain object from the _APP_DOMAIN_TARGET_CNAME environment variable without
checking if it is empty, causing a DNS validator with an empty hostname to be
added and leading to false validation failures. To fix this, add a condition to
check that _APP_DOMAIN_TARGET_CNAME is not empty before instantiating the Domain
object and adding the DNS validator. This prevents unnecessary lookups and
maintains the logic that at least one validator must be configured.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants

0