Skip to content

Feat/project onboarding stages#3

Open
DhirenMhatre wants to merge 4 commits into
1.9.xfrom
feat/project-onboarding-stages
Open

Feat/project onboarding stages#3
DhirenMhatre wants to merge 4 commits into
1.9.xfrom
feat/project-onboarding-stages

Conversation

@DhirenMhatre

Copy link
Copy Markdown

What does this PR do?

(Provide a description of what this PR does and why it's needed.)

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?

Add configurable onboarding stages keyed by SDK method, persist completion
in project onboarding JSON on successful API responses, and expose listStages
and updateStage routes with stages.read/write scopes and stage/stageList models.

Made-with: Cursor
Emit console realtime when onboarding stages complete in API shutdown.
Add Project/StagesBase + StagesConsoleClientTest following Platforms pattern.

Made-with: Cursor
@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

Policy Check Failed

✗ 3/3 policy checks failed:

• Need 2 more approval(s) (0/2) — comment LGTM or approve via review
• Missing ticket reference (expected: JIRA-, ENG-, #*)
• 12 code file(s) changed but no test files added


To merge this PR:

  1. Address the failed checks listed above
  2. Ensure branch protection requires the codity/policy-check status

Configure policies in your dashboard

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

PR Summary

What Changed

  • Added project onboarding stages tracking to monitor user progress through setup tasks (database, storage, function creation).
  • New API endpoints let users list stages and mark them as skipped.
  • Automatic stage completion hooks trigger when corresponding SDK methods succeed.

Key Changes by Area

API: New endpoints GET /projects/{projectId}/stages and PATCH /projects/{projectId}/stages/{stageId} with stages.read and stages.write scopes.

Data Model: onboarding JSON field on projects stores stage status (pending, completed, skipped) with timestamps. New Stage and StageList response models.

Automation: Hook in app/controllers/shared/api.php:800-860 auto-completes stages when databases.create, storage.createBucket, or functions.create succeed.

Files Changed

File Changes Summary
app/config/collections/platform.php Added onboarding JSON field to projects collection
app/config/onboarding.php Stage definitions mapping SDK methods to stage IDs
app/config/roles.php Added stages permissions to roles
app/config/scopes/project.php New stages.read and stages.write scopes
app/controllers/shared/api.php Auto-completion hook for SDK method calls
app/init/configs.php Onboarding config initialization
app/init/constants.php New constants for onboarding
app/init/models.php Registered Stage and StageList models
docs/references/projects/list-stages.md API documentation for list endpoint
docs/references/projects/update-stage.md API documentation for update endpoint
src/Appwrite/Platform/Modules/Projects/Http/Stages/Update.php PATCH endpoint implementation
src/Appwrite/Platform/Modules/Projects/Http/Stages/XList.php GET endpoint implementation
src/Appwrite/Platform/Modules/Projects/Services/Http.php Registered new stage routes
src/Appwrite/Utopia/Response.php Added MODEL_STAGE and MODEL_STAGE_LIST constants
src/Appwrite/Utopia/Response/Model/Project.php Added onboarding field to project model
src/Appwrite/Utopia/Response/Model/Stage.php New response model for stage data
tests/e2e/Services/Project/StagesBase.php E2E test base with helper methods
tests/e2e/Services/Project/StagesConsoleClientTest.php Console client test implementation

Review Focus Areas

  • Hook placement in api.php for auto-completion timing and error handling.
  • Permission checks in stage update endpoint for skip vs complete transitions.
  • JSON schema validation for onboarding field structure.

Architecture

Design Decisions: Automatic completion uses a centralized hook rather than per-endpoint changes. This keeps SDK methods clean but couples completion logic to API controller internals. The onboarding JSON field avoids schema migrations for new stages.

Scalability & Extensibility: Stage definitions are config-driven (app/config/onboarding.php). New stages require config entry and hook mapping only. Out of scope: user-defined stages or stage dependencies.

Risks: Hook-based auto-completion may miss edge cases (async operations, partial failures). Intentional: JSON field limits queryability of stage status. Unintentional: No cleanup if SDK call succeeds but subsequent operation fails.

Merge Status

NOT MERGEABLE — PR Score 55/100, below threshold (50)

  • [H2] 3 critical dependency CVEs detected
  • [H3] 1 high-risk (strong copyleft) license detected
  • [H6] Code quality raw score (29) is below merge floor (40)

'at' => DateTime::now(),
'actorType' => $this->resolveActorType($apiKey, $user, $mode),
];
$project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('onboarding', $byStageId));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Functional Medium

After a stage is skipped, a successful API call that matches that stage (for example PATCH /v1/projects/{id}/stages/create_database with skip=true followed by creating a database) will never mark it completed because the shutdown hook in app/controllers/shared/api.php now treats skipped as terminal.

Change the shared API hook to only preserve COMPLETED as terminal, or add explicit logic here to let real route completion overwrite SKIPPED with COMPLETED when the mapped SDK action later succeeds.

Prompt for AI assistance

Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:

You are an expert php developer with deep knowledge of security, performance, and best practices.

### Context

File: src/Appwrite/Platform/Modules/Projects/Http/Stages/Update.php
Lines: 90-90
Issue Type: functional-medium
Severity: medium

Issue Description:
After a stage is skipped, a successful API call that matches that stage (for example PATCH /v1/projects/{id}/stages/create_database with skip=true followed by creating a database) will never mark it completed because the shutdown hook in app/controllers/shared/api.php now treats skipped as terminal.

Current Code:
$project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('onboarding', $byStageId));

---

### Instructions

1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow php best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed

### Constraints

- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready

---


Like Dislike Create Issue Jira

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

Security Scan Summary

Metric Value
Vulnerabilities Critical: 0
Overall Risk Clean
Files Scanned 18

No critical security issues detected

Scan completed in 34.6s

Security scan powered by Codity.ai

@greptile-apps

greptile-apps Bot commented May 23, 2026

Copy link
Copy Markdown

Greptile Summary

This PR introduces a project onboarding system with three stages (create_database, create_bucket, create_function) that auto-complete via the API shutdown hook when the matching SDK method succeeds, plus two new admin-scoped endpoints (GET /v1/projects/:id/stages and PATCH /v1/projects/:id/stages/:stageId) to read and manually skip stages.

  • Auto-complete hook (app/controllers/shared/api.php): on every successful non-console response, the shutdown hook matches the route's SDK label against the onboarding config, updates project.onboarding in the platform DB, and fires a projects.[id].stages.[id].complete realtime event — but leaves the Realtime queue's subscribers set to ['console'], corrupting the immediately following main-request realtime dispatch.
  • Schema change (app/config/collections/platform.php): a new onboarding JSON column is added to the projects collection definition with no accompanying migration class, so existing deployments will be missing the column after an upgrade.
  • New endpoints (Stages/Update.php, Stages/XList.php): follow the same patterns as existing project sub-resource controllers; Update.php defaults skip to true, making a body-less PATCH silently destructive.

Confidence Score: 2/5

Not safe to merge — the shutdown hook change corrupts realtime event delivery for all project-API calls that trigger a stage, and the missing migration would break existing deployments on upgrade.

Two independent defects affect core infrastructure paths: the subscribers leak silently misdirects realtime events on every matched SDK call in production, and the absent migration means the onboarding column will not exist on upgraded instances, causing write failures the moment any stage-eligible API call completes.

app/controllers/shared/api.php (subscriber leak) and app/config/collections/platform.php (missing migration) are the two files that need fixes before this is safe to merge.

Important Files Changed

Filename Overview
app/controllers/shared/api.php Shutdown hook extended to auto-complete onboarding stages; subscribers set to ['console'] for the stage event is not cleared before the existing main-request realtime dispatch, breaking fan-out for all project-API calls that trigger a stage.
app/config/collections/platform.php New onboarding JSON attribute added to the projects collection schema; no migration class accompanies the change, so existing deployments will lack the column and writes will fail on upgrade.
src/Appwrite/Platform/Modules/Projects/Http/Stages/Update.php New PATCH endpoint to skip a stage; logic guards against overwriting a completed status but defaults skip to true, making a no-body request destructive.
src/Appwrite/Platform/Modules/Projects/Http/Stages/XList.php New GET endpoint that lists all configured onboarding stages with their per-project status; follows the same pattern as existing project sub-resource controllers.
app/config/onboarding.php Defines three onboarding stages (create_database, create_bucket, create_function) and builds an O(1) SDK-key index; straightforward config with no issues.
src/Appwrite/Utopia/Response/Model/Stage.php New response model for a Stage document with id, sdk, status, at, and actorType fields; correctly typed and consistent with existing model patterns.
tests/e2e/Services/Project/StagesBase.php E2E tests covering list, skip, no-op, and unauthenticated scenarios; count assertion is hardcoded to 3 stages which would break if the config changes.
tests/e2e/Services/Project/StagesConsoleClientTest.php Thin test class that wires StagesBase, ProjectCustom, and SideConsole scopes; no issues.

Sequence Diagram

sequenceDiagram
    participant Client
    participant API as API Route Handler
    participant Shutdown as Shutdown Hook
    participant DB as dbForPlatform
    participant RT as Realtime Queue

    Client->>API: POST /databases (or similar SDK method)
    API->>DB: create document
    API->>RT: setEvent(databases.[id].create)
    API-->>Shutdown: hand off

    Shutdown->>Shutdown: check 2xx and not console project
    Shutdown->>Shutdown: match sdkLabel to stageId
    Shutdown->>DB: updateDocument(projects, onboarding)
    Shutdown->>RT: reset()
    Shutdown->>RT: setSubscribers(['console']) + setEvent(stage.complete)
    Shutdown->>RT: trigger() — stage-complete event fires

    Note over Shutdown,RT: subscribers stays ['console']

    Shutdown->>RT: from(queueForEvents) — does NOT reset subscribers
    Shutdown->>RT: trigger() — main event sent to console only

    Client->>API: GET /v1/projects/:id/stages
    API->>DB: getDocument(projects, projectId)
    DB-->>API: project with onboarding map
    API-->>Client: Stage list

    Client->>API: PATCH /v1/projects/:id/stages/:stageId
    API->>DB: getDocument + updateDocument (SKIPPED)
    API-->>Client: Stage object
Loading

Comments Outside Diff (1)

  1. app/controllers/shared/api.php, line 150-163 (link)

    P1 Realtime subscribers leaks into main-request event dispatch

    Event::from() copies project, event, params, payload, and context — but it does not copy or reset the subscribers field, which is declared only on the Realtime subclass. After the stage-complete event fires with setSubscribers(['console']), that value stays on the object. When the existing shutdown-hook code immediately runs $queueForRealtime->from($queueForEvents)->trigger(), $this->subscribers is still ['console'], so the primary request's realtime event (e.g., databases.create, storage.createBucket) is broadcast only to the console subscriber instead of the correct project subscriber. Realtime subscriptions on every affected project-API call would silently stop working.

    Call $queueForRealtime->setSubscribers([]) (or add a reset of subscribers in Realtime::reset()) after the stage trigger() so the subsequent dispatch restores default fan-out behaviour.

Reviews (1): Last reviewed commit: "docs: add projects stages API reference ..." | Re-trigger Greptile

Comment on lines +346 to +355
'$id' => ID::custom('onboarding'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => 65536,
'signed' => true,
'required' => false,
'default' => [],
'array' => false,
'filters' => ['json'],
],

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 No database migration for the new onboarding attribute

The onboarding attribute is added to the platform.php schema definition, but this PR does not include a corresponding migration class (e.g., V25.php). Existing deployments that upgrade will not have the onboarding column in their projects collection. Any attempt by the shutdown hook or the Update endpoint to call updateDocument('projects', …, new Document(['onboarding' => …])) on an upgraded installation will fail at the database layer. New fresh installs are unaffected because platform.php is consumed at collection-creation time, not on upgrade.

))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('stageId', '', new Text(64), 'Stage ID.')
->param('skip', true, new Boolean(), 'Mark the stage as skipped.', true)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 The skip parameter defaults to true, meaning a PATCH request sent with no body will silently skip the stage. This is a destructive default; callers who forget to include the body (or who intend a no-op read) will permanently mark stages as skipped. Defaulting to false preserves the current status unless the caller explicitly opts in.

Suggested change
->param('skip', true, new Boolean(), 'Mark the stage as skipped.', true)
->param('skip', false, new Boolean(), 'Mark the stage as skipped.', true)

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

Dependency vulnerability scanning

Metric Value
Vulnerabilities Found 9
Scanner composer audit
View vulnerability details (9 items)

1. phpseclib/phpseclib 3.0.51

CVE: GHSA-3qpq-r242-jqj7
Severity: CRITICAL
Fixed in: 1.0.29

phpseclib has a CVE-2024-27355 mitigation bypass — OID amplification DoS in ASN1::decodeOID()


2. webonyx/graphql-php 14.11.10

CVE: GHSA-68jq-c3rv-pcrr
Severity: MEDIUM
Fixed in: 15.31.5

graphql-php is affected by a Denial of Service via quadratic complexity in OverlappingFieldsCanBeMerged validation


3. webonyx/graphql-php 14.11.10

CVE: GHSA-fc86-6rv6-2jpm
Severity: CRITICAL
Fixed in: 15.32.2

webonyx/graphql-php has quadratic validation cost in OverlappingFieldsCanBeMerged via inline fragments


4. webonyx/graphql-php 14.11.10

CVE: GHSA-r7cg-qjjm-xhqq
Severity: CRITICAL
Fixed in: 15.32.3

webonyx/graphql-php has unbounded recursion in parser that causes stack overflow on crafted nested input


5. twig/twig 3.14.2

CVE: GHSA-24x9-r6q4-q93w
Severity: HIGH
Fixed in: 3.26.0

Twig: template_from_string() escapes a SourcePolicy-driven sandbox via synthesized template name


6. twig/twig 3.14.2

CVE: GHSA-4j38-f5cw-54h7
Severity: MEDIUM
Fixed in: 3.26.0

Twig: The spaceless filter implicitly marks its output as safe


7. twig/twig 3.14.2

CVE: GHSA-7fxw-r6jv-74c8
Severity: HIGH
Fixed in: 3.26.0

Twig: {% sandbox %}{% include %} skips checkSecurity() on cached templates (incomplete fix for CVE-2024-45411)


8. twig/twig 3.14.2

CVE: GHSA-7p85-w9px-jpjp
Severity: HIGH
Fixed in: 3.26.0

Twig: PHP code injection via {% use %} template name


9. twig/twig 3.14.2

CVE: GHSA-vcc8-phrv-43wj
Severity: MEDIUM
Fixed in: 3.26.0

Twig: Sandbox property allowlist bypass via the column filter (array_column on objects)

Powered by Codity.ai · Docs

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

License Compliance Scan

Metric Value
Packages Scanned 580
High Risk (Strong Copyleft) 1
Medium Risk (Weak Copyleft) 17
Low Risk (Permissive) 558
Unknown License 4

Strong copyleft licenses detected - review before merging

Weak copyleft licenses found - verify compatibility

Some packages have unknown licenses - manual review required

High Risk Licenses - 1 packages

GPL-2.0-or-later (1 packages):

  • enshrined/svg-sanitize 0.22.0
Medium Risk Licenses - 17 packages

Apache-2.0 AND LGPL-3.0-or-later (3 packages):

  • @img/sharp-win32-arm64 0.34.5
  • @img/sharp-win32-x64 0.34.5
  • @img/sharp-win32-ia32 0.34.5

Apache-2.0 AND LGPL-3.0-or-later AND MIT (1 packages):

  • @img/sharp-wasm32 0.34.5

LGPL-2.1-only (1 packages):

  • phpmailer/phpmailer 6.9.1

LGPL-2.1-or-later (1 packages):

  • php-amqplib/php-amqplib 3.7.4

LGPL-3.0-or-later (11 packages):

  • @img/sharp-libvips-linux-arm 1.2.4
  • @img/sharp-libvips-darwin-arm64 1.2.4
  • @img/sharp-libvips-linux-arm64 1.2.4
  • @img/sharp-libvips-darwin-x64 1.2.4
  • @img/sharp-libvips-linux-riscv64 1.2.4
  • @img/sharp-libvips-linux-ppc64 1.2.4
  • @img/sharp-libvips-linux-s390x 1.2.4
  • @img/sharp-libvips-linux-x64 1.2.4
  • @img/sharp-libvips-linuxmusl-arm64 1.2.4
  • @img/sharp-libvips-linuxmusl-x64 1.2.4
  • ...and 1 more
Unknown Licenses - 4 packages
  • lru-cache 11.2.7 (BlueOak-1.0.0)
  • sax 1.5.0 (BlueOak-1.0.0)
  • zod-to-ts 1.2.0
  • lru-cache 11.2.6 (BlueOak-1.0.0)

Powered by Codity.ai · Docs

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

Code Quality Report — test-org-codity/appwrite · PR #3

Scanned: 2026-05-23 09:10 UTC | Score: 29/100 | Provider: github

Executive Summary

Severity Count
Critical 0
High 1
Medium 2
Low 78
Top Findings

[CQ-LLM-001] app/controllers/shared/api.php:800 (Complexity · HIGH)

Issue: The action function has a high cyclomatic complexity due to multiple nested conditions and loops.
Suggestion: Refactor the action function to reduce complexity by breaking it into smaller, more manageable functions.

if ($response->getStatusCode() >= 200 && $response->getStatusCode() < 300 && $project->getId() !== 'console') { ... }

[CQ-LLM-002] app/controllers/shared/api.php:800 (Error_Handling · MEDIUM)

Issue: There is a lack of error handling for database operations, which may lead to unhandled exceptions.
Suggestion: Implement try-catch blocks around database operations to handle potential exceptions.

$authorization->skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), new Document([...])));

[CQ-LLM-003] app/controllers/shared/api.php:800 (Documentation · MEDIUM)

Issue: Missing docstring for the action function, which is a public API.
Suggestion: Add a docstring to describe the purpose and parameters of the action function.

->action(function (Http $utopia, Request $request, Response $response, ...) { ... }

[CQ-008] app/config/collections/platform.php:349 (Maintainability · LOW)

Issue: Magic number 65536 in code
Suggestion: Extract to a named constant

'size' => 65536,

[CQ-009] app/controllers/shared/api.php:810 (Style · LOW)

Issue: Line exceeds 120 characters (581 chars)
Suggestion: Break long lines into multiple lines for readability

    ->action(function (Http $utopia, Request $request, Response $response, Document $project, User $user, Event $queueFo...

[CQ-009] app/controllers/shared/api.php:815 (Style · LOW)

Issue: Line exceeds 120 characters (133 chars)
Suggestion: Break long lines into multiple lines for readability

         * Persist completed stage when the route matches a configured SDK method (stored on project as `onboarding`: st...

[CQ-008] app/controllers/shared/api.php:817 (Maintainability · LOW)

Issue: Magic number 200 in code
Suggestion: Extract to a named constant

if ($response->getStatusCode() >= 200 && $response->getStatusCode() < 300 && $project->getId() !== 'console') {

[CQ-009] app/controllers/shared/api.php:822 (Style · LOW)

Issue: Line exceeds 120 characters (125 chars)
Suggestion: Break long lines into multiple lines for readability

                foreach ($sdkLabel instanceof Method ? [$sdkLabel] : (\is_array($sdkLabel) ? $sdkLabel : []) as $sdkMeth...

[CQ-009] app/controllers/shared/api.php:823 (Style · LOW)

Issue: Line exceeds 120 characters (144 chars)
Suggestion: Break long lines into multiple lines for readability

                    if ($sdkMethod instanceof Method && isset($sdkIndex[$k = $sdkMethod->getNamespace() . '.' . $sdkMeth...

[CQ-002] app/controllers/shared/api.php:823 (Complexity · LOW)

Issue: Deep nesting detected (depth ~5)
Suggestion: Extract nested blocks into helper functions

if ($sdkMethod instanceof Method && isset($sdkIndex[$k = $sdkMethod->getNamespace() . '.' . $sdkMethod->getMethodName()])) {

Per-File Breakdown

File Critical High Medium Low Total
app/config/collections/platform.php 0 0 0 1 1
app/controllers/shared/api.php 0 1 2 43 46
app/init/configs.php 0 0 0 1 1
app/init/constants.php 0 0 0 1 1
app/init/models.php 0 0 0 1 1
docs/references/projects/list-stages.md 0 0 0 1 2
docs/references/projects/update-stage.md 0 0 0 1 1
src/Appwrite/Platform/Modules/Projects/Http/Stages/Update.php 0 0 0 10 10
src/Appwrite/Platform/Modules/Projects/Http/Stages/XList.php 0 0 0 4 4
src/Appwrite/Utopia/Response/Model/Project.php 0 0 0 1 1
src/Appwrite/Utopia/Response/Model/Stage.php 0 0 0 1 1
tests/e2e/Services/Project/StagesBase.php 0 0 0 12 12

Recommendations

  1. Resolve High severity issues, especially error handling gaps and performance bottlenecks.
  • Run automated tests after applying fixes to verify no regressions.

@DhirenMhatre

Copy link
Copy Markdown
Author

@codity review

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

Policy Check Failed

✗ 3/3 policy checks failed:

• Need 2 more approval(s) (0/2) — comment LGTM or approve via review
• Missing ticket reference (expected: JIRA-, ENG-, #*)
• 12 code file(s) changed but no test files added


To merge this PR:

  1. Address the failed checks listed above
  2. Ensure branch protection requires the codity/policy-check status

Configure policies in your dashboard

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

PR Summary

What Changed

  • Added project onboarding stages to track user progress through setup milestones (database, storage, functions).
  • New API endpoints let users view stage status and skip stages manually.
  • Automatic completion hooks trigger when users call matching SDK methods.

Key Changes by Area

API: Added GET /projects/{projectId}/stages and PATCH /projects/{projectId}/stages/{stageId} endpoints with stages.read and stages.write scopes.

Data Model: New onboarding JSON field on projects stores stage status, timestamps, and actor metadata. Stage definitions live in app/config/onboarding.php.

Auto-Completion: Hook in app/controllers/shared/api.php marks stages complete when SDK methods like databases.create are called.

Files Changed

File Changes Summary
app/config/collections/platform.php Added onboarding JSON field to projects collection
app/config/onboarding.php Stage definitions mapping SDK methods to stage IDs
app/config/roles.php Updated role permissions for new scopes
app/config/scopes/project.php Added stages.read and stages.write scopes
app/controllers/shared/api.php Auto-completion hook for SDK method calls
app/init/configs.php Loaded onboarding config
app/init/constants.php Added onboarding-related constants
app/init/models.php Registered Stage and StageList response models
docs/references/projects/list-stages.md API documentation for list endpoint
docs/references/projects/update-stage.md API documentation for update endpoint
src/Appwrite/Platform/Modules/Projects/Http/Stages/Update.php PATCH endpoint handler for skipping stages
src/Appwrite/Platform/Modules/Projects/Http/Stages/XList.php GET endpoint handler for listing stages
src/Appwrite/Platform/Modules/Projects/Services/Http.php Registered new stage routes
src/Appwrite/Utopia/Response.php Added MODEL_STAGE and MODEL_STAGE_LIST constants
src/Appwrite/Utopia/Response/Model/Project.php Added onboarding field to project response
src/Appwrite/Utopia/Response/Model/Stage.php New response model for stage data
tests/e2e/Services/Project/StagesBase.php E2E tests for stage operations
tests/e2e/Services/Project/StagesConsoleClientTest.php Console client specific test class

Review Focus Areas

  • Hook logic in app/controllers/shared/api.php for race conditions on concurrent SDK calls.
  • Authorization checks in stage endpoints: ensure users can only modify their own project stages.
  • JSON field size limits: onboarding field may grow with more stages.

Architecture

Design Decisions: Chose JSON field over separate collection to avoid join complexity and keep reads fast. Stage-to-SDK mapping is hardcoded in config for simplicity. Intentionally no migration for existing projects: they start with empty onboarding state.

Scalability & Extensibility: Adding new stages requires config change only. Out of scope: webhooks on stage change, progress percentages, or per-user (vs per-project) tracking.

Risks: Hook runs on every API call. Monitor latency impact. Actor type detection relies on request context which may be incomplete for internal/service calls.

Merge Status

NOT MERGEABLE — PR Score 43/100, below threshold (50)

  • [H2] 3 critical dependency CVEs detected
  • [H3] 1 high-risk (strong copyleft) license detected
  • [H4] PR quality score (43) is below merge floor (50)
  • [H6] Code quality raw score (29) is below merge floor (40)

: (! $user->isEmpty()
? ($mode === APP_MODE_ADMIN ? ACTIVITY_TYPE_ADMIN : ACTIVITY_TYPE_USER)
: ACTIVITY_TYPE_GUEST);
$byStageId[$stageId] = [

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Functional High

After PATCH /v1/projects/{projectId}/stages/create_database with {"skip":true}, a later successful databases.create call still overwrites that skipped stage to completed because this hook updates the stale $project snapshot instead of reloading onboarding state first.

Before computing $done and writing completion, reload the current project document from dbForPlatform (or perform a conditional/merge update) so an already-skipped stage is not reverted by a later request using an older injected $project instance.

Prompt for AI assistance

Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:

You are an expert php developer with deep knowledge of security, performance, and best practices.

### Context

File: app/controllers/shared/api.php
Lines: 846-846
Issue Type: functional-high
Severity: high

Issue Description:
After PATCH /v1/projects/{projectId}/stages/create_database with {"skip":true}, a later successful databases.create call still overwrites that skipped stage to completed because this hook updates the stale $project snapshot instead of reloading onboarding state first.

Current Code:
$byStageId[$stageId] = [
    'status' => ONBOARDING_STATUS_COMPLETED,
    'at' => DateTime::now(),
    'actorType' => $actorType,
];

---

### Instructions

1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow php best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed

### Constraints

- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready

---


Like Dislike Create Issue Jira

Comment on lines +82 to +90
if ($skip) {
$prev = \is_array($row) ? ($row['status'] ?? '') : '';
if ($prev !== ONBOARDING_STATUS_COMPLETED) {
$byStageId[$stageId] = [
'status' => ONBOARDING_STATUS_SKIPPED,
'at' => DateTime::now(),
'actorType' => $this->resolveActorType($apiKey, $user, $mode),
];
$project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('onboarding', $byStageId));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Security High

This update reads and writes the project without an atomic compare or transaction, so a concurrent successful stage completion can be overwritten with skipped; re-read under a lock or perform a conditional update that preserves completed.

Suggested fix
        if ($skip) {
            $project = $dbForPlatform->getDocument('projects', $projectId);
            $byStageId = $project->getAttribute('onboarding', []);
            if (! \is_array($byStageId)) {
                $byStageId = [];
            }

            $row = \is_array($byStageId[$stageId] ?? null) ? $byStageId[$stageId] : null;
            $prev = \is_array($row) ? ($row['status'] ?? '') : '';
            if ($prev !== ONBOARDING_STATUS_COMPLETED) {
                $byStageId[$stageId] = [
                    'status' => ONBOARDING_STATUS_SKIPPED,
                    'at' => DateTime::now(),
                    'actorType' => $this->resolveActorType($apiKey, $user, $mode),
                ];
                $project = $dbForPlatform->updateDocument('projects', $project->getId(), new Document([
                    'onboarding' => $byStageId,
                ]));
            }
        }
Prompt for AI assistance

Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:

You are an expert php developer with deep knowledge of security, performance, and best practices.

### Context

File: src/Appwrite/Platform/Modules/Projects/Http/Stages/Update.php
Lines: 82-90
Issue Type: security-high
Severity: high

Issue Description:
This update reads and writes the project without an atomic compare or transaction, so a concurrent successful stage completion can be overwritten with `skipped`; re-read under a lock or perform a conditional update that preserves `completed`.

Current Code:
        if ($skip) {
            $prev = \is_array($row) ? ($row['status'] ?? '') : '';
            if ($prev !== ONBOARDING_STATUS_COMPLETED) {
                $byStageId[$stageId] = [
                    'status' => ONBOARDING_STATUS_SKIPPED,
                    'at' => DateTime::now(),
                    'actorType' => $this->resolveActorType($apiKey, $user, $mode),
                ];
                $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('onboarding', $byStageId));

---

### Instructions

1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow php best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed

### Constraints

- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready

---


Like Dislike Create Issue Jira

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

Security Scan Summary

Metric Value
Vulnerabilities Critical: 0
Overall Risk Clean
Files Scanned 18

No critical security issues detected

Scan completed in 53.2s

Security scan powered by Codity.ai

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

Dependency vulnerability scanning

Metric Value
Vulnerabilities Found 9
Scanner composer audit
View vulnerability details (9 items)

1. phpseclib/phpseclib 3.0.51

CVE: GHSA-3qpq-r242-jqj7
Severity: CRITICAL
Fixed in: 1.0.29

phpseclib has a CVE-2024-27355 mitigation bypass — OID amplification DoS in ASN1::decodeOID()


2. webonyx/graphql-php 14.11.10

CVE: GHSA-68jq-c3rv-pcrr
Severity: MEDIUM
Fixed in: 15.31.5

graphql-php is affected by a Denial of Service via quadratic complexity in OverlappingFieldsCanBeMerged validation


3. webonyx/graphql-php 14.11.10

CVE: GHSA-fc86-6rv6-2jpm
Severity: CRITICAL
Fixed in: 15.32.2

webonyx/graphql-php has quadratic validation cost in OverlappingFieldsCanBeMerged via inline fragments


4. webonyx/graphql-php 14.11.10

CVE: GHSA-r7cg-qjjm-xhqq
Severity: CRITICAL
Fixed in: 15.32.3

webonyx/graphql-php has unbounded recursion in parser that causes stack overflow on crafted nested input


5. twig/twig 3.14.2

CVE: GHSA-24x9-r6q4-q93w
Severity: HIGH
Fixed in: 3.26.0

Twig: template_from_string() escapes a SourcePolicy-driven sandbox via synthesized template name


6. twig/twig 3.14.2

CVE: GHSA-4j38-f5cw-54h7
Severity: MEDIUM
Fixed in: 3.26.0

Twig: The spaceless filter implicitly marks its output as safe


7. twig/twig 3.14.2

CVE: GHSA-7fxw-r6jv-74c8
Severity: HIGH
Fixed in: 3.26.0

Twig: {% sandbox %}{% include %} skips checkSecurity() on cached templates (incomplete fix for CVE-2024-45411)


8. twig/twig 3.14.2

CVE: GHSA-7p85-w9px-jpjp
Severity: HIGH
Fixed in: 3.26.0

Twig: PHP code injection via {% use %} template name


9. twig/twig 3.14.2

CVE: GHSA-vcc8-phrv-43wj
Severity: MEDIUM
Fixed in: 3.26.0

Twig: Sandbox property allowlist bypass via the column filter (array_column on objects)

Powered by Codity.ai · Docs

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

License Compliance Scan

Metric Value
Packages Scanned 580
High Risk (Strong Copyleft) 1
Medium Risk (Weak Copyleft) 17
Low Risk (Permissive) 558
Unknown License 4

Strong copyleft licenses detected - review before merging

Weak copyleft licenses found - verify compatibility

Some packages have unknown licenses - manual review required

High Risk Licenses - 1 packages

GPL-2.0-or-later (1 packages):

  • enshrined/svg-sanitize 0.22.0
Medium Risk Licenses - 17 packages

Apache-2.0 AND LGPL-3.0-or-later (3 packages):

  • @img/sharp-win32-x64 0.34.5
  • @img/sharp-win32-arm64 0.34.5
  • @img/sharp-win32-ia32 0.34.5

Apache-2.0 AND LGPL-3.0-or-later AND MIT (1 packages):

  • @img/sharp-wasm32 0.34.5

LGPL-2.1-only (1 packages):

  • phpmailer/phpmailer 6.9.1

LGPL-2.1-or-later (1 packages):

  • php-amqplib/php-amqplib 3.7.4

LGPL-3.0-or-later (11 packages):

  • @img/sharp-libvips-darwin-x64 1.2.4
  • @img/sharp-libvips-darwin-arm64 1.2.4
  • @img/sharp-libvips-linux-arm 1.2.4
  • @img/sharp-libvips-linux-arm64 1.2.4
  • @img/sharp-libvips-linux-ppc64 1.2.4
  • @img/sharp-libvips-linux-riscv64 1.2.4
  • @img/sharp-libvips-linux-s390x 1.2.4
  • @img/sharp-libvips-linux-x64 1.2.4
  • @img/sharp-libvips-linuxmusl-x64 1.2.4
  • @img/sharp-libvips-linuxmusl-arm64 1.2.4
  • ...and 1 more
Unknown Licenses - 4 packages
  • lru-cache 11.2.7 (BlueOak-1.0.0)
  • sax 1.5.0 (BlueOak-1.0.0)
  • zod-to-ts 1.2.0
  • lru-cache 11.2.6 (BlueOak-1.0.0)

Powered by Codity.ai · Docs

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

Code Quality Report — test-org-codity/appwrite · PR #3

Scanned: 2026-05-23 09:32 UTC | Score: 29/100 | Provider: github

Executive Summary

Severity Count
Critical 0
High 1
Medium 2
Low 78
Top Findings

[CQ-LLM-001] app/controllers/shared/api.php:800 (Complexity · HIGH)

Issue: The action function has a high cyclomatic complexity due to multiple nested conditions and loops.
Suggestion: Refactor the action function to reduce complexity by breaking it into smaller, more manageable functions.

if ($response->getStatusCode() >= 200 && $response->getStatusCode() < 300 && $project->getId() !== 'console') { ... }

[CQ-LLM-002] app/controllers/shared/api.php:800 (Error_Handling · MEDIUM)

Issue: There is a lack of error handling for database operations, which may lead to unhandled exceptions.
Suggestion: Implement try-catch blocks around database operations to handle potential exceptions.

$authorization->skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), new Document([...])));

[CQ-LLM-003] app/controllers/shared/api.php:800 (Documentation · MEDIUM)

Issue: Missing docstring for the action function, which is a public API.
Suggestion: Add a docstring to describe the purpose and parameters of the action function.

->action(function (Http $utopia, Request $request, Response $response, ...) { ... }

[CQ-008] app/config/collections/platform.php:349 (Maintainability · LOW)

Issue: Magic number 65536 in code
Suggestion: Extract to a named constant

'size' => 65536,

[CQ-009] app/controllers/shared/api.php:810 (Style · LOW)

Issue: Line exceeds 120 characters (581 chars)
Suggestion: Break long lines into multiple lines for readability

    ->action(function (Http $utopia, Request $request, Response $response, Document $project, User $user, Event $queueFo...

[CQ-009] app/controllers/shared/api.php:815 (Style · LOW)

Issue: Line exceeds 120 characters (133 chars)
Suggestion: Break long lines into multiple lines for readability

         * Persist completed stage when the route matches a configured SDK method (stored on project as `onboarding`: st...

[CQ-008] app/controllers/shared/api.php:817 (Maintainability · LOW)

Issue: Magic number 200 in code
Suggestion: Extract to a named constant

if ($response->getStatusCode() >= 200 && $response->getStatusCode() < 300 && $project->getId() !== 'console') {

[CQ-009] app/controllers/shared/api.php:822 (Style · LOW)

Issue: Line exceeds 120 characters (125 chars)
Suggestion: Break long lines into multiple lines for readability

                foreach ($sdkLabel instanceof Method ? [$sdkLabel] : (\is_array($sdkLabel) ? $sdkLabel : []) as $sdkMeth...

[CQ-009] app/controllers/shared/api.php:823 (Style · LOW)

Issue: Line exceeds 120 characters (144 chars)
Suggestion: Break long lines into multiple lines for readability

                    if ($sdkMethod instanceof Method && isset($sdkIndex[$k = $sdkMethod->getNamespace() . '.' . $sdkMeth...

[CQ-002] app/controllers/shared/api.php:823 (Complexity · LOW)

Issue: Deep nesting detected (depth ~5)
Suggestion: Extract nested blocks into helper functions

if ($sdkMethod instanceof Method && isset($sdkIndex[$k = $sdkMethod->getNamespace() . '.' . $sdkMethod->getMethodName()])) {

Per-File Breakdown

File Critical High Medium Low Total
app/config/collections/platform.php 0 0 0 1 1
app/controllers/shared/api.php 0 1 2 43 46
app/init/configs.php 0 0 0 1 1
app/init/constants.php 0 0 0 1 1
app/init/models.php 0 0 0 1 1
docs/references/projects/list-stages.md 0 0 0 1 2
docs/references/projects/update-stage.md 0 0 0 1 1
src/Appwrite/Platform/Modules/Projects/Http/Stages/Update.php 0 0 0 10 10
src/Appwrite/Platform/Modules/Projects/Http/Stages/XList.php 0 0 0 4 4
src/Appwrite/Utopia/Response/Model/Project.php 0 0 0 1 1
src/Appwrite/Utopia/Response/Model/Stage.php 0 0 0 1 1
tests/e2e/Services/Project/StagesBase.php 0 0 0 12 12

Recommendations

  1. Resolve High severity issues, especially error handling gaps and performance bottlenecks.
  • Run automated tests after applying fixes to verify no regressions.

@DhirenMhatre

Copy link
Copy Markdown
Author

@codity review

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

Policy Check Failed

✗ 3/3 policy checks failed:

• Need 2 more approval(s) (0/2) — comment LGTM or approve via review
• Missing ticket reference (expected: JIRA-, ENG-, #*)
• 12 code file(s) changed but no test files added


To merge this PR:

  1. Address the failed checks listed above
  2. Ensure branch protection requires the codity/policy-check status

Configure policies in your dashboard

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

PR Summary

What Changed

  • Added project onboarding stages to track user progress through setup tasks (database, bucket, function creation).
  • Stages auto-complete when matching SDK methods return 2xx responses, with manual skip/update endpoints available.

Key Changes by Area

Database: Added onboarding JSON column to projects collection in app/config/collections/platform.php:345-355.

API: New endpoints in src/Appwrite/Platform/Modules/Projects/Services/Http.php:37-38 for listing and updating stages. Auto-completion hook added in app/controllers/shared/api.php:800-860.

Permissions: New stages.read and stages.write scopes in app/config/roles.php and app/config/scopes/project.php.

Models: Added Stage and StageList response models. Updated Project model with onboarding field.

Config: New app/config/onboarding.php defines 3 stages mapped to SDK methods.

Files Changed

File Changes Summary
app/config/collections/platform.php Added onboarding JSON column to projects collection
app/config/onboarding.php New config defining 3 onboarding stages with SDK method mappings
app/config/roles.php Added stages.read and stages.write permissions
app/config/scopes/project.php Added stage-related scopes
app/controllers/shared/api.php Auto-completion hook for SDK method calls
app/init/configs.php Config initialization updates
app/init/constants.php Constants updates for new feature
app/init/models.php Registered Stage and StageList models
docs/references/projects/list-stages.md API documentation for list endpoint
docs/references/projects/update-stage.md API documentation for update endpoint
src/Appwrite/Platform/Modules/Projects/Http/Stages/Update.php PATCH endpoint for stage updates
src/Appwrite/Platform/Modules/Projects/Http/Stages/XList.php GET endpoint for listing stages
src/Appwrite/Platform/Modules/Projects/Services/Http.php Registered new stage routes
src/Appwrite/Utopia/Response.php Added Stage and StageList model references
src/Appwrite/Utopia/Response/Model/Project.php Added onboarding field to project response
src/Appwrite/Utopia/Response/Model/Stage.php New Stage response model
tests/e2e/Services/Project/StagesBase.php Base test class with helpers
tests/e2e/Services/Project/StagesConsoleClientTest.php E2E tests for console client

Review Focus Areas

  • Auto-completion logic in app/controllers/shared/api.php:800-860: verify it only triggers on genuine success cases, not retries or partial failures.
  • Permission checks in stage endpoints: ensure stages.write properly restricts manual updates while allowing auto-completion via internal flow.
  • JSON schema validation for onboarding field: confirm it handles missing or malformed data gracefully on existing projects.

Architecture

Design Decisions: Chose JSON column over normalized table to keep stage definitions flexible and avoid migrations when adding new stages. Auto-completion uses response interception rather than service-level hooks to minimize code changes across multiple services.

Risks: JSON column limits queryability of stage history. This is intentional (stages are per-project, not queried across projects). Actor type tracking (user/admin/key) relies on request context availability in shared API hook. Verify this holds for all SDK paths, including server-side and CLI usage.

if (! \is_array($byStageId)) {
$byStageId = [];
}
$done = \is_array($byStageId[$stageId] ?? null) ? ($byStageId[$stageId]['status'] ?? '') : '';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Functional Medium

After a client skips stage create_database via PATCH /v1/projects/{projectId}/stages/create_database, the next successful POST /v1/databases still overwrites that skipped row to completed, breaking the cross-endpoint contract that skipped stages remain skipped.

Before marking a route-derived stage complete, reload the latest project document from dbForPlatform and honor any existing skipped status, or make the stage update endpoint and shutdown hook use a shared compare-and-swap helper to prevent stale in-memory $project data from overriding prior writes.

Prompt for AI assistance

Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:

You are an expert php developer with deep knowledge of security, performance, and best practices.

### Context

File: app/controllers/shared/api.php
Lines: 834-834
Issue Type: functional-medium
Severity: medium

Issue Description:
After a client skips stage `create_database` via `PATCH /v1/projects/{projectId}/stages/create_database`, the next successful `POST /v1/databases` still overwrites that skipped row to `completed`, breaking the cross-endpoint contract that skipped stages remain skipped.

Current Code:
$done = \is_array($byStageId[$stageId] ?? null) ? ($byStageId[$stageId]['status'] ?? '') : '';
if ($done !== ONBOARDING_STATUS_COMPLETED && $done !== ONBOARDING_STATUS_SKIPPED) {
    $actorType = ($apiKey !== null && $apiKey->getRole() === User::ROLE_APPS)
        ? match ($apiKey->getType()) {
            API_KEY_ACCOUNT => ACTIVITY_TYPE_KEY_ACCOUNT,

---

### Instructions

1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow php best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed

### Constraints

- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready

---


Like Dislike Create Issue Jira

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

Security Scan Summary

Metric Value
Vulnerabilities Critical: 0
Overall Risk Clean
Files Scanned 18

No critical security issues detected

Scan completed in 38.2s

Security scan powered by Codity.ai

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

Dependency vulnerability scanning

Metric Value
Vulnerabilities Found 9
Scanner composer audit
View vulnerability details (9 items)

1. phpseclib/phpseclib 3.0.51

CVE: GHSA-3qpq-r242-jqj7
Severity: CRITICAL
Fixed in: 1.0.29

phpseclib has a CVE-2024-27355 mitigation bypass — OID amplification DoS in ASN1::decodeOID()


2. webonyx/graphql-php 14.11.10

CVE: GHSA-68jq-c3rv-pcrr
Severity: MEDIUM
Fixed in: 15.31.5

graphql-php is affected by a Denial of Service via quadratic complexity in OverlappingFieldsCanBeMerged validation


3. webonyx/graphql-php 14.11.10

CVE: GHSA-fc86-6rv6-2jpm
Severity: CRITICAL
Fixed in: 15.32.2

webonyx/graphql-php has quadratic validation cost in OverlappingFieldsCanBeMerged via inline fragments


4. webonyx/graphql-php 14.11.10

CVE: GHSA-r7cg-qjjm-xhqq
Severity: CRITICAL
Fixed in: 15.32.3

webonyx/graphql-php has unbounded recursion in parser that causes stack overflow on crafted nested input


5. twig/twig 3.14.2

CVE: GHSA-24x9-r6q4-q93w
Severity: HIGH
Fixed in: 3.26.0

Twig: template_from_string() escapes a SourcePolicy-driven sandbox via synthesized template name


6. twig/twig 3.14.2

CVE: GHSA-4j38-f5cw-54h7
Severity: MEDIUM
Fixed in: 3.26.0

Twig: The spaceless filter implicitly marks its output as safe


7. twig/twig 3.14.2

CVE: GHSA-7fxw-r6jv-74c8
Severity: HIGH
Fixed in: 3.26.0

Twig: {% sandbox %}{% include %} skips checkSecurity() on cached templates (incomplete fix for CVE-2024-45411)


8. twig/twig 3.14.2

CVE: GHSA-7p85-w9px-jpjp
Severity: HIGH
Fixed in: 3.26.0

Twig: PHP code injection via {% use %} template name


9. twig/twig 3.14.2

CVE: GHSA-vcc8-phrv-43wj
Severity: MEDIUM
Fixed in: 3.26.0

Twig: Sandbox property allowlist bypass via the column filter (array_column on objects)

Powered by Codity.ai · Docs

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

License Compliance Scan

Metric Value
Packages Scanned 580
High Risk (Strong Copyleft) 1
Medium Risk (Weak Copyleft) 17
Low Risk (Permissive) 558
Unknown License 4

Strong copyleft licenses detected - review before merging

Weak copyleft licenses found - verify compatibility

Some packages have unknown licenses - manual review required

High Risk Licenses - 1 packages

GPL-2.0-or-later (1 packages):

  • enshrined/svg-sanitize 0.22.0
Medium Risk Licenses - 17 packages

Apache-2.0 AND LGPL-3.0-or-later (3 packages):

  • @img/sharp-win32-arm64 0.34.5
  • @img/sharp-win32-ia32 0.34.5
  • @img/sharp-win32-x64 0.34.5

Apache-2.0 AND LGPL-3.0-or-later AND MIT (1 packages):

  • @img/sharp-wasm32 0.34.5

LGPL-2.1-only (1 packages):

  • phpmailer/phpmailer 6.9.1

LGPL-2.1-or-later (1 packages):

  • php-amqplib/php-amqplib 3.7.4

LGPL-3.0-or-later (11 packages):

  • @img/sharp-libvips-darwin-x64 1.2.4
  • @img/sharp-libvips-darwin-arm64 1.2.4
  • @img/sharp-libvips-linux-ppc64 1.2.4
  • @img/sharp-libvips-linux-arm64 1.2.4
  • @img/sharp-libvips-linux-x64 1.2.4
  • @img/sharp-libvips-linux-s390x 1.2.4
  • @img/sharp-libvips-linux-riscv64 1.2.4
  • @img/sharp-libvips-linux-arm 1.2.4
  • @img/sharp-libvips-linuxmusl-x64 1.2.4
  • @img/sharp-libvips-linuxmusl-arm64 1.2.4
  • ...and 1 more
Unknown Licenses - 4 packages
  • lru-cache 11.2.7 (BlueOak-1.0.0)
  • sax 1.5.0 (BlueOak-1.0.0)
  • zod-to-ts 1.2.0
  • lru-cache 11.2.6 (BlueOak-1.0.0)

Powered by Codity.ai · Docs

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

Code Quality Report — test-org-codity/appwrite · PR #3

Scanned: 2026-05-23 09:54 UTC | Score: 29/100 | Provider: github

Executive Summary

Severity Count
Critical 0
High 1
Medium 2
Low 78
Top Findings

[CQ-LLM-001] app/controllers/shared/api.php:800 (Complexity · HIGH)

Issue: The action function has a high cyclomatic complexity due to multiple nested conditions and loops.
Suggestion: Refactor the action function to reduce complexity by breaking it into smaller, more manageable functions.

->action(function (Http $utopia, Request $request, Response $response, Document $project, User $user, Event $queueForEvents, Audit $queueForAudits, Context $usage, UsagePublisher $publisherForUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Func $queueForFunctions, Event $queueForWebhooks, Realtime $queueForRealtime, Database $dbForProject, Database $dbForPlatform, Authorization $authorization, callable $timelimit, EventProcessor $eventProcessor, Bus $bus, ?Key $apiKey, string $mode) use ($parseLabel) { ... }

[CQ-LLM-002] app/controllers/shared/api.php:800 (Error_Handling · MEDIUM)

Issue: There is a lack of error handling for database operations, which may lead to unhandled exceptions.
Suggestion: Implement try-catch blocks around database operations to handle potential exceptions.

$authorization->skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), new Document([ 'onboarding' => $byStageId, ])));

[CQ-LLM-003] app/controllers/shared/api.php:800 (Documentation · MEDIUM)

Issue: Missing docstring for the action function, which is a public API.
Suggestion: Add a docstring to describe the purpose, parameters, and return value of the action function.

->action(function (Http $utopia, Request $request, Response $response, Document $project, User $user, ...

[CQ-008] app/config/collections/platform.php:349 (Maintainability · LOW)

Issue: Magic number 65536 in code
Suggestion: Extract to a named constant

'size' => 65536,

[CQ-009] app/controllers/shared/api.php:810 (Style · LOW)

Issue: Line exceeds 120 characters (581 chars)
Suggestion: Break long lines into multiple lines for readability

    ->action(function (Http $utopia, Request $request, Response $response, Document $project, User $user, Event $queueFo...

[CQ-009] app/controllers/shared/api.php:815 (Style · LOW)

Issue: Line exceeds 120 characters (133 chars)
Suggestion: Break long lines into multiple lines for readability

         * Persist completed stage when the route matches a configured SDK method (stored on project as `onboarding`: st...

[CQ-008] app/controllers/shared/api.php:817 (Maintainability · LOW)

Issue: Magic number 200 in code
Suggestion: Extract to a named constant

if ($response->getStatusCode() >= 200 && $response->getStatusCode() < 300 && $project->getId() !== 'console') {

[CQ-009] app/controllers/shared/api.php:822 (Style · LOW)

Issue: Line exceeds 120 characters (125 chars)
Suggestion: Break long lines into multiple lines for readability

                foreach ($sdkLabel instanceof Method ? [$sdkLabel] : (\is_array($sdkLabel) ? $sdkLabel : []) as $sdkMeth...

[CQ-009] app/controllers/shared/api.php:823 (Style · LOW)

Issue: Line exceeds 120 characters (144 chars)
Suggestion: Break long lines into multiple lines for readability

                    if ($sdkMethod instanceof Method && isset($sdkIndex[$k = $sdkMethod->getNamespace() . '.' . $sdkMeth...

[CQ-002] app/controllers/shared/api.php:823 (Complexity · LOW)

Issue: Deep nesting detected (depth ~5)
Suggestion: Extract nested blocks into helper functions

if ($sdkMethod instanceof Method && isset($sdkIndex[$k = $sdkMethod->getNamespace() . '.' . $sdkMethod->getMethodName()])) {

Per-File Breakdown

File Critical High Medium Low Total
app/config/collections/platform.php 0 0 0 1 1
app/controllers/shared/api.php 0 1 2 43 46
app/init/configs.php 0 0 0 1 1
app/init/constants.php 0 0 0 1 1
app/init/models.php 0 0 0 1 1
docs/references/projects/list-stages.md 0 0 0 1 2
docs/references/projects/update-stage.md 0 0 0 1 1
src/Appwrite/Platform/Modules/Projects/Http/Stages/Update.php 0 0 0 10 10
src/Appwrite/Platform/Modules/Projects/Http/Stages/XList.php 0 0 0 4 4
src/Appwrite/Utopia/Response/Model/Project.php 0 0 0 1 1
src/Appwrite/Utopia/Response/Model/Stage.php 0 0 0 1 1
tests/e2e/Services/Project/StagesBase.php 0 0 0 12 12

Recommendations

  1. Resolve High severity issues, especially error handling gaps and performance bottlenecks.
  • Run automated tests after applying fixes to verify no regressions.

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

Merge Status

NOT MERGEABLE — PR Score 41/100, below threshold (50)

  • [H2] 3 critical dependency CVEs detected
  • [H3] 1 high-risk (strong copyleft) license detected
  • [H4] PR quality score (41) is below merge floor (50)
  • [H6] Code quality raw score (29) is below merge floor (40)

@DhirenMhatre

Copy link
Copy Markdown
Author

@codity review

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

Policy Check Failed

✗ 3/3 policy checks failed:

• Need 2 more approval(s) (0/2) — comment LGTM or approve via review
• Missing ticket reference (expected: JIRA-, ENG-, #*)
• 12 code file(s) changed but no test files added


To merge this PR:

  1. Address the failed checks listed above
  2. Ensure branch protection requires the codity/policy-check status

Configure policies in your dashboard

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

PR review started! Estimated time: 5-10 minutes.

Custom Review Instructions Detected
source: context file (CLAUDE.md / .cursorrules)

@AGENTS.md
Learn More

View Analytics Dashboard

Ask Codity questions: Mention @codity {your question} in a comment to get answers about the code.

Trigger a manual review: Comment @codity review on a PR or MR.

Generate unit tests: Comment /generate-tests to auto-generate tests for Go, Python, Ruby, JavaScript, TypeScript, and Java files.

Run security scan again: Comment /security-scan to run SAST and dependency vulnerability scans for all major languages in your repo.

View Full Docs

@DhirenMhatre

Copy link
Copy Markdown
Author

@codity review

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

PR Summary

What Changed

  • Added project onboarding stages to track setup progress (database, bucket, function creation) with status and actor attribution.
  • New API endpoints let users list stages and skip/update them, with auto-completion when SDK methods succeed.
  • Added stages.read and stages.write scopes for access control.

Key Changes by Area

Database: Added onboarding JSON column to projects collection in app/config/collections/platform.php:342.

Configuration: Created app/config/onboarding.php defining 3 stages mapped to SDK methods.

API: New endpoints in src/Appwrite/Platform/Modules/Projects/Http/Stages/ for listing and updating stages. Hook in app/controllers/shared/api.php:800 auto-completes stages on matching SDK calls.

Models: Added Stage and StageList response models; extended Project model with onboarding field.

Authorization: New stages.read and stages.write scopes in app/config/scopes/project.php.

Files Changed

File Changes Summary
app/config/collections/platform.php Added onboarding JSON column to projects collection
app/config/onboarding.php New config defining 3 onboarding stages with SDK method mappings
app/config/roles.php Updated roles to include new stage scopes
app/config/scopes/project.php Added stages.read and stages.write scopes
app/controllers/shared/api.php Added hook to auto-complete stages on SDK method success
app/init/configs.php Registered new onboarding config
app/init/constants.php Added onboarding-related constants
app/init/models.php Registered Stage and StageList response models
docs/references/projects/list-stages.md API documentation for list stages endpoint
docs/references/projects/update-stage.md API documentation for update stage endpoint
src/Appwrite/Platform/Modules/Projects/Http/Stages/Update.php PATCH endpoint to skip/update stage status
src/Appwrite/Platform/Modules/Projects/Http/Stages/XList.php GET endpoint to list all stages with status
src/Appwrite/Platform/Modules/Projects/Services/Http.php Registered new stage routes
src/Appwrite/Utopia/Response.php Added MODEL_STAGE and MODEL_STAGE_LIST constants
src/Appwrite/Utopia/Response/Model/Project.php Added onboarding field to project response
src/Appwrite/Utopia/Response/Model/Stage.php New response model for stage data
tests/e2e/Services/Project/StagesBase.php Base test class with stage test cases
tests/e2e/Services/Project/StagesConsoleClientTest.php Console client specific stage tests

Review Focus Areas

  • Auto-completion logic: Verify the hook in app/controllers/shared/api.php:800 correctly matches SDK methods to stage definitions without false positives.
  • Permission boundaries: Check that stages.read/stages.write scopes are properly enforced and that guests cannot modify stages.
  • JSON schema: Review the onboarding column structure for migration safety and query support.

Architecture

  • Design Decisions: Stages use a JSON column rather than separate table to avoid joins and simplify per-project queries. Actor type tracking (user/admin/key/guest) supports audit without full audit logging. Auto-completion via controller hook keeps SDK methods unchanged but creates tight coupling between API layer and onboarding logic.
  • Scalability & Extensibility: JSON storage limits complex querying (e.g., "find all projects with pending database stage"). Out of scope: indexing strategy, stage ordering constraints, stage dependencies.
  • Risks: Hook-based auto-completion may miss edge cases (network failures, batch operations) or double-complete on retries. Intentional: tight coupling for simplicity. Unintentional: no transaction boundary between SDK call and stage update.

Merge Status

NOT MERGEABLE — PR Score 39/100, below threshold (50)

  • [H2] 3 critical dependency CVEs detected
  • [H3] 1 high-risk (strong copyleft) license detected
  • [H4] PR quality score (39) is below merge floor (50)
  • [H6] Code quality raw score (29) is below merge floor (40)

if ($skip) {
$prev = \is_array($row) ? ($row['status'] ?? '') : '';
if ($prev !== ONBOARDING_STATUS_COMPLETED) {
$byStageId[$stageId] = [

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Functional Medium

After a client skips a stage via PATCH /v1/projects/{projectId}/stages/{stageId}, the later successful API call for that stage (for example creating a database) never flips it to completed because the shutdown hook in app/controllers/shared/api.php explicitly refuses to overwrite skipped status.

Suggested change
$byStageId[$stageId] = [
Either allow the shutdown hook to transition skipped -> completed when the mapped SDK action succeeds, or persist a distinct "dismissed" state for manual skips that does not block later automatic completion.
Prompt for AI assistance

Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:

You are an expert php developer with deep knowledge of security, performance, and best practices.

### Context

File: src/Appwrite/Platform/Modules/Projects/Http/Stages/Update.php
Lines: 85-85
Issue Type: functional-medium
Severity: medium

Issue Description:
After a client skips a stage via PATCH /v1/projects/{projectId}/stages/{stageId}, the later successful API call for that stage (for example creating a database) never flips it to completed because the shutdown hook in app/controllers/shared/api.php explicitly refuses to overwrite skipped status.

Current Code:
$byStageId[$stageId] = [
    'status' => ONBOARDING_STATUS_SKIPPED,
    'at' => DateTime::now(),
    'actorType' => $this->resolveActorType($apiKey, $user, $mode),
];

---

### Instructions

1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow php best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed

### Constraints

- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready

---


Like Dislike Create Issue Jira

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

Security Scan Summary

Metric Value
Vulnerabilities Critical: 0
Overall Risk Clean
Files Scanned 18

No critical security issues detected

Scan completed in 33.0s

Security scan powered by Codity.ai

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

Dependency vulnerability scanning

Metric Value
Vulnerabilities Found 9
Scanner composer audit
View vulnerability details (9 items)

1. phpseclib/phpseclib 3.0.51

CVE: GHSA-3qpq-r242-jqj7
Severity: CRITICAL
Fixed in: 1.0.29

phpseclib has a CVE-2024-27355 mitigation bypass — OID amplification DoS in ASN1::decodeOID()


2. webonyx/graphql-php 14.11.10

CVE: GHSA-68jq-c3rv-pcrr
Severity: MEDIUM
Fixed in: 15.31.5

graphql-php is affected by a Denial of Service via quadratic complexity in OverlappingFieldsCanBeMerged validation


3. webonyx/graphql-php 14.11.10

CVE: GHSA-fc86-6rv6-2jpm
Severity: CRITICAL
Fixed in: 15.32.2

webonyx/graphql-php has quadratic validation cost in OverlappingFieldsCanBeMerged via inline fragments


4. webonyx/graphql-php 14.11.10

CVE: GHSA-r7cg-qjjm-xhqq
Severity: CRITICAL
Fixed in: 15.32.3

webonyx/graphql-php has unbounded recursion in parser that causes stack overflow on crafted nested input


5. twig/twig 3.14.2

CVE: GHSA-24x9-r6q4-q93w
Severity: HIGH
Fixed in: 3.26.0

Twig: template_from_string() escapes a SourcePolicy-driven sandbox via synthesized template name


6. twig/twig 3.14.2

CVE: GHSA-4j38-f5cw-54h7
Severity: MEDIUM
Fixed in: 3.26.0

Twig: The spaceless filter implicitly marks its output as safe


7. twig/twig 3.14.2

CVE: GHSA-7fxw-r6jv-74c8
Severity: HIGH
Fixed in: 3.26.0

Twig: {% sandbox %}{% include %} skips checkSecurity() on cached templates (incomplete fix for CVE-2024-45411)


8. twig/twig 3.14.2

CVE: GHSA-7p85-w9px-jpjp
Severity: HIGH
Fixed in: 3.26.0

Twig: PHP code injection via {% use %} template name


9. twig/twig 3.14.2

CVE: GHSA-vcc8-phrv-43wj
Severity: MEDIUM
Fixed in: 3.26.0

Twig: Sandbox property allowlist bypass via the column filter (array_column on objects)

Powered by Codity.ai · Docs

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

License Compliance Scan

Metric Value
Packages Scanned 580
High Risk (Strong Copyleft) 1
Medium Risk (Weak Copyleft) 17
Low Risk (Permissive) 558
Unknown License 4

Strong copyleft licenses detected - review before merging

Weak copyleft licenses found - verify compatibility

Some packages have unknown licenses - manual review required

High Risk Licenses - 1 packages

GPL-2.0-or-later (1 packages):

  • enshrined/svg-sanitize 0.22.0
Medium Risk Licenses - 17 packages

Apache-2.0 AND LGPL-3.0-or-later (3 packages):

  • @img/sharp-win32-arm64 0.34.5
  • @img/sharp-win32-x64 0.34.5
  • @img/sharp-win32-ia32 0.34.5

Apache-2.0 AND LGPL-3.0-or-later AND MIT (1 packages):

  • @img/sharp-wasm32 0.34.5

LGPL-2.1-only (1 packages):

  • phpmailer/phpmailer 6.9.1

LGPL-2.1-or-later (1 packages):

  • php-amqplib/php-amqplib 3.7.4

LGPL-3.0-or-later (11 packages):

  • @img/sharp-libvips-linux-arm64 1.2.4
  • @img/sharp-libvips-darwin-arm64 1.2.4
  • @img/sharp-libvips-darwin-x64 1.2.4
  • @img/sharp-libvips-linux-arm 1.2.4
  • @img/sharp-libvips-linux-ppc64 1.2.4
  • @img/sharp-libvips-linux-riscv64 1.2.4
  • @img/sharp-libvips-linux-s390x 1.2.4
  • @img/sharp-libvips-linux-x64 1.2.4
  • @img/sharp-libvips-linuxmusl-arm64 1.2.4
  • @img/sharp-libvips-linuxmusl-x64 1.2.4
  • ...and 1 more
Unknown Licenses - 4 packages
  • lru-cache 11.2.7 (BlueOak-1.0.0)
  • sax 1.5.0 (BlueOak-1.0.0)
  • zod-to-ts 1.2.0
  • lru-cache 11.2.6 (BlueOak-1.0.0)

Powered by Codity.ai · Docs

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

Code Quality Report — test-org-codity/appwrite · PR #3

Scanned: 2026-05-23 10:27 UTC | Score: 29/100 | Provider: github

Executive Summary

Severity Count
Critical 0
High 1
Medium 2
Low 78
Top Findings

[CQ-LLM-001] app/controllers/shared/api.php:800 (Complexity · HIGH)

Issue: The action function has a high cyclomatic complexity due to multiple nested conditions and loops.
Suggestion: Refactor the action function to reduce complexity by breaking it into smaller, more manageable functions.

->action(function (Http $utopia, Request $request, Response $response, Document $project, User $user, Event $queueForEvents, Audit $queueForAudits, Context $usage, UsagePublisher $publisherForUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Func $queueForFunctions, Event $queueForWebhooks, Realtime $queueForRealtime, Database $dbForProject, Database $dbForPlatform, Authorization $authorization, callable $timelimit, EventProcessor $eventProcessor, Bus $bus, ?Key $apiKey, string $mode) use ($parseLabel) { ... }

[CQ-LLM-002] app/controllers/shared/api.php:800 (Error_Handling · MEDIUM)

Issue: Potentially swallowed exceptions in the database update operation without proper error handling.
Suggestion: Add error handling to manage exceptions that may arise during the database update operation.

$authorization->skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), new Document([ 'onboarding' => $byStageId, ])));

[CQ-LLM-003] app/controllers/shared/api.php:800 (Documentation · MEDIUM)

Issue: Missing docstring for the action function, which is a public API.
Suggestion: Add a docstring to describe the purpose and parameters of the action function.

->action(function (Http $utopia, Request $request, Response $response, Document $project, User $user, Event $queueForEvents, Audit $queueForAudits, Context $usage, UsagePublisher $publisherForUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Func $queueForFunctions, Event $queueForWebhooks, Realtime $queueForRealtime, Database $dbForProject, Database $dbForPlatform, Authorization $authorization, callable $timelimit, EventProcessor $eventProcessor, Bus $bus, ?Key $apiKey, string $mode) use ($parseLabel) { ... }

[CQ-008] app/config/collections/platform.php:349 (Maintainability · LOW)

Issue: Magic number 65536 in code
Suggestion: Extract to a named constant

'size' => 65536,

[CQ-009] app/controllers/shared/api.php:810 (Style · LOW)

Issue: Line exceeds 120 characters (581 chars)
Suggestion: Break long lines into multiple lines for readability

    ->action(function (Http $utopia, Request $request, Response $response, Document $project, User $user, Event $queueFo...

[CQ-009] app/controllers/shared/api.php:815 (Style · LOW)

Issue: Line exceeds 120 characters (133 chars)
Suggestion: Break long lines into multiple lines for readability

         * Persist completed stage when the route matches a configured SDK method (stored on project as `onboarding`: st...

[CQ-008] app/controllers/shared/api.php:817 (Maintainability · LOW)

Issue: Magic number 200 in code
Suggestion: Extract to a named constant

if ($response->getStatusCode() >= 200 && $response->getStatusCode() < 300 && $project->getId() !== 'console') {

[CQ-009] app/controllers/shared/api.php:822 (Style · LOW)

Issue: Line exceeds 120 characters (125 chars)
Suggestion: Break long lines into multiple lines for readability

                foreach ($sdkLabel instanceof Method ? [$sdkLabel] : (\is_array($sdkLabel) ? $sdkLabel : []) as $sdkMeth...

[CQ-009] app/controllers/shared/api.php:823 (Style · LOW)

Issue: Line exceeds 120 characters (144 chars)
Suggestion: Break long lines into multiple lines for readability

                    if ($sdkMethod instanceof Method && isset($sdkIndex[$k = $sdkMethod->getNamespace() . '.' . $sdkMeth...

[CQ-002] app/controllers/shared/api.php:823 (Complexity · LOW)

Issue: Deep nesting detected (depth ~5)
Suggestion: Extract nested blocks into helper functions

if ($sdkMethod instanceof Method && isset($sdkIndex[$k = $sdkMethod->getNamespace() . '.' . $sdkMethod->getMethodName()])) {

Per-File Breakdown

File Critical High Medium Low Total
app/config/collections/platform.php 0 0 0 1 1
app/controllers/shared/api.php 0 1 2 43 47
app/init/configs.php 0 0 0 1 1
app/init/constants.php 0 0 0 1 1
app/init/models.php 0 0 0 1 1
docs/references/projects/list-stages.md 0 0 0 1 1
docs/references/projects/update-stage.md 0 0 0 1 1
src/Appwrite/Platform/Modules/Projects/Http/Stages/Update.php 0 0 0 10 10
src/Appwrite/Platform/Modules/Projects/Http/Stages/XList.php 0 0 0 4 4
src/Appwrite/Utopia/Response/Model/Project.php 0 0 0 1 1
src/Appwrite/Utopia/Response/Model/Stage.php 0 0 0 1 1
tests/e2e/Services/Project/StagesBase.php 0 0 0 12 12

Recommendations

  1. Resolve High severity issues, especially error handling gaps and performance bottlenecks.
  • Run automated tests after applying fixes to verify no regressions.

@DhirenMhatre

Copy link
Copy Markdown
Author

@codity review

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

Policy Check Failed

✗ 3/3 policy checks failed:

• Need 2 more approval(s) (0/2) — comment LGTM or approve via review
• Missing ticket reference (expected: JIRA-, ENG-, #*)
• 12 code file(s) changed but no test files added


To merge this PR:

  1. Address the failed checks listed above
  2. Ensure branch protection requires the codity/policy-check status

Configure policies in your dashboard

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

PR Summary

What Changed

  • Added project onboarding stages tracking for database, bucket, and function creation milestones.
  • New API endpoints let users list stages and skip incomplete ones.
  • Automatic stage completion hooks into existing SDK method calls.

Key Changes by Area

API: Added GET /projects/{projectId}/stages and PATCH /projects/{projectId}/stages/{stageId} endpoints in src/Appwrite/Platform/Modules/Projects/Services/Http.php:37-38.

Data Model: Added onboarding JSON field to projects collection. Stage definitions map to SDK methods in app/config/onboarding.php.

Permissions: New stages.read and stages.write scopes added to project roles.

Auto-Completion: Hook in app/controllers/shared/api.php:800-860 marks stages complete on successful SDK calls, tracking timestamp and actor type.

Files Changed

File Changes Summary
app/config/collections/platform.php Added onboarding JSON field to projects collection
app/config/onboarding.php Stage definitions mapping SDK methods to milestones
app/config/roles.php Added stages.read and stages.write permissions
app/config/scopes/project.php New stage-related scopes
app/controllers/shared/api.php Auto-completion hook for SDK method calls
app/init/configs.php Onboarding config initialization
app/init/constants.php Stage-related constants
app/init/models.php Registered MODEL_STAGE and MODEL_STAGE_LIST
docs/references/projects/list-stages.md API documentation for list endpoint
docs/references/projects/update-stage.md API documentation for update endpoint
src/Appwrite/Platform/Modules/Projects/Http/Stages/Update.php PATCH endpoint handler
src/Appwrite/Platform/Modules/Projects/Http/Stages/XList.php GET endpoint handler
src/Appwrite/Platform/Modules/Projects/Services/Http.php Route registration for new endpoints
src/Appwrite/Utopia/Response.php Added stage response models
src/Appwrite/Utopia/Response/Model/Project.php Extended with onboarding field
src/Appwrite/Utopia/Response/Model/Stage.php New stage model definition
tests/e2e/Services/Project/StagesBase.php Base test class for stage functionality
tests/e2e/Services/Project/StagesConsoleClientTest.php Console client specific tests

Review Focus Areas

  • Auto-completion hook logic in app/controllers/shared/api.php:800-860 and its performance impact on all SDK calls.
  • Permission boundaries between stages.read and stages.write scopes.
  • JSON structure migration path for existing projects without onboarding data.

Architecture

Design Decisions: Stages are stored as JSON in the project document rather than a separate collection. This keeps reads fast and avoids joins. The tradeoff is limited queryability of stage history.

Scalability & Extensibility: Actor type tracking (user/admin/API key/guest) supports future audit requirements. New stages require config changes only, no schema migrations.

Risks: The auto-completion hook runs on every SDK method call. This is intentional but adds overhead to hot paths. The onboarding JSON field grows unbounded if stage history accumulates. This is acceptable for the expected stage count (3 stages).

Merge Status

NOT MERGEABLE — PR Score 40/100, below threshold (50)

  • [H2] 3 critical dependency CVEs detected
  • [H3] 1 high-risk (strong copyleft) license detected
  • [H4] PR quality score (40) is below merge floor (50)
  • [H6] Code quality raw score (30) is below merge floor (40)

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

Security Scan Summary

Metric Value
Vulnerabilities Critical: 0
Overall Risk Clean
Files Scanned 18

No critical security issues detected

Scan completed in 33.4s

Security scan powered by Codity.ai

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

Dependency vulnerability scanning

Metric Value
Vulnerabilities Found 9
Scanner composer audit
View vulnerability details (9 items)

1. phpseclib/phpseclib 3.0.51

CVE: GHSA-3qpq-r242-jqj7
Severity: CRITICAL
Fixed in: 1.0.29

phpseclib has a CVE-2024-27355 mitigation bypass — OID amplification DoS in ASN1::decodeOID()


2. webonyx/graphql-php 14.11.10

CVE: GHSA-68jq-c3rv-pcrr
Severity: MEDIUM
Fixed in: 15.31.5

graphql-php is affected by a Denial of Service via quadratic complexity in OverlappingFieldsCanBeMerged validation


3. webonyx/graphql-php 14.11.10

CVE: GHSA-fc86-6rv6-2jpm
Severity: CRITICAL
Fixed in: 15.32.2

webonyx/graphql-php has quadratic validation cost in OverlappingFieldsCanBeMerged via inline fragments


4. webonyx/graphql-php 14.11.10

CVE: GHSA-r7cg-qjjm-xhqq
Severity: CRITICAL
Fixed in: 15.32.3

webonyx/graphql-php has unbounded recursion in parser that causes stack overflow on crafted nested input


5. twig/twig 3.14.2

CVE: GHSA-24x9-r6q4-q93w
Severity: HIGH
Fixed in: 3.26.0

Twig: template_from_string() escapes a SourcePolicy-driven sandbox via synthesized template name


6. twig/twig 3.14.2

CVE: GHSA-4j38-f5cw-54h7
Severity: MEDIUM
Fixed in: 3.26.0

Twig: The spaceless filter implicitly marks its output as safe


7. twig/twig 3.14.2

CVE: GHSA-7fxw-r6jv-74c8
Severity: HIGH
Fixed in: 3.26.0

Twig: {% sandbox %}{% include %} skips checkSecurity() on cached templates (incomplete fix for CVE-2024-45411)


8. twig/twig 3.14.2

CVE: GHSA-7p85-w9px-jpjp
Severity: HIGH
Fixed in: 3.26.0

Twig: PHP code injection via {% use %} template name


9. twig/twig 3.14.2

CVE: GHSA-vcc8-phrv-43wj
Severity: MEDIUM
Fixed in: 3.26.0

Twig: Sandbox property allowlist bypass via the column filter (array_column on objects)

Powered by Codity.ai · Docs

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

License Compliance Scan

Metric Value
Packages Scanned 580
High Risk (Strong Copyleft) 1
Medium Risk (Weak Copyleft) 17
Low Risk (Permissive) 558
Unknown License 4

Strong copyleft licenses detected - review before merging

Weak copyleft licenses found - verify compatibility

Some packages have unknown licenses - manual review required

High Risk Licenses - 1 packages

GPL-2.0-or-later (1 packages):

  • enshrined/svg-sanitize 0.22.0
Medium Risk Licenses - 17 packages

Apache-2.0 AND LGPL-3.0-or-later (3 packages):

  • @img/sharp-win32-arm64 0.34.5
  • @img/sharp-win32-ia32 0.34.5
  • @img/sharp-win32-x64 0.34.5

Apache-2.0 AND LGPL-3.0-or-later AND MIT (1 packages):

  • @img/sharp-wasm32 0.34.5

LGPL-2.1-only (1 packages):

  • phpmailer/phpmailer 6.9.1

LGPL-2.1-or-later (1 packages):

  • php-amqplib/php-amqplib 3.7.4

LGPL-3.0-or-later (11 packages):

  • @img/sharp-libvips-darwin-arm64 1.2.4
  • @img/sharp-libvips-darwin-x64 1.2.4
  • @img/sharp-libvips-linux-arm 1.2.4
  • @img/sharp-libvips-linux-arm64 1.2.4
  • @img/sharp-libvips-linux-riscv64 1.2.4
  • @img/sharp-libvips-linux-ppc64 1.2.4
  • @img/sharp-libvips-linux-x64 1.2.4
  • @img/sharp-libvips-linux-s390x 1.2.4
  • @img/sharp-libvips-linuxmusl-arm64 1.2.4
  • @img/sharp-libvips-linuxmusl-x64 1.2.4
  • ...and 1 more
Unknown Licenses - 4 packages
  • lru-cache 11.2.7 (BlueOak-1.0.0)
  • sax 1.5.0 (BlueOak-1.0.0)
  • zod-to-ts 1.2.0
  • lru-cache 11.2.6 (BlueOak-1.0.0)

Powered by Codity.ai · Docs

@codity-dm

codity-dm Bot commented May 23, 2026

Copy link
Copy Markdown

Code Quality Report — test-org-codity/appwrite · PR #3

Scanned: 2026-05-23 12:11 UTC | Score: 30/100 | Provider: github

Executive Summary

Severity Count
Critical 0
High 1
Medium 2
Low 77
Top Findings

[CQ-LLM-001] app/controllers/shared/api.php:800 (Complexity · HIGH)

Issue: The action function has a high cyclomatic complexity due to multiple nested conditions and loops.
Suggestion: Refactor the action function to reduce complexity by breaking it into smaller, more manageable functions.

->action(function (Http $utopia, Request $request, Response $response, Document $project, User $user, Event $queueForEvents, Audit $queueForAudits, Context $usage, UsagePublisher $publisherForUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Func $queueForFunctions, Event $queueForWebhooks, Realtime $queueForRealtime, Database $dbForProject, Database $dbForPlatform, Authorization $authorization, callable $timelimit, EventProcessor $eventProcessor, Bus $bus, ?Key $apiKey, string $mode) use ($parseLabel) { ... }

[CQ-LLM-002] app/controllers/shared/api.php:800 (Error_Handling · MEDIUM)

Issue: Potentially swallowed exceptions in the database update operation without proper error handling.
Suggestion: Implement error handling for the database update operation to ensure exceptions are logged or handled appropriately.

$authorization->skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), new Document([ 'onboarding' => $byStageId, ])));

[CQ-LLM-003] app/controllers/shared/api.php:800 (Documentation · MEDIUM)

Issue: Missing docstring for the action function, which is a public API.
Suggestion: Add a docstring to describe the purpose, parameters, and return value of the action function.

->action(function (Http $utopia, Request $request, Response $response, Document $project, User $user, Event $queueForEvents, Audit $queueForAudits, Context $usage, UsagePublisher $publisherForUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Func $queueForFunctions, Event $queueForWebhooks, Realtime $queueForRealtime, Database $dbForProject, Database $dbForPlatform, Authorization $authorization, callable $timelimit, EventProcessor $eventProcessor, Bus $bus, ?Key $apiKey, string $mode) use ($parseLabel) { ... }

[CQ-008] app/config/collections/platform.php:349 (Maintainability · LOW)

Issue: Magic number 65536 in code
Suggestion: Extract to a named constant

'size' => 65536,

[CQ-LLM-004] app/controllers/shared/api.php:800 (Maintainability · LOW)

Issue: Use of magic strings for status codes and onboarding status.
Suggestion: Define constants for status codes and onboarding statuses to improve readability and maintainability.

$done !== ONBOARDING_STATUS_COMPLETED && $done !== ONBOARDING_STATUS_SKIPPED

[CQ-009] app/controllers/shared/api.php:810 (Style · LOW)

Issue: Line exceeds 120 characters (581 chars)
Suggestion: Break long lines into multiple lines for readability

    ->action(function (Http $utopia, Request $request, Response $response, Document $project, User $user, Event $queueFo...

[CQ-009] app/controllers/shared/api.php:815 (Style · LOW)

Issue: Line exceeds 120 characters (133 chars)
Suggestion: Break long lines into multiple lines for readability

         * Persist completed stage when the route matches a configured SDK method (stored on project as `onboarding`: st...

[CQ-008] app/controllers/shared/api.php:817 (Maintainability · LOW)

Issue: Magic number 200 in code
Suggestion: Extract to a named constant

if ($response->getStatusCode() >= 200 && $response->getStatusCode() < 300 && $project->getId() !== 'console') {

[CQ-009] app/controllers/shared/api.php:822 (Style · LOW)

Issue: Line exceeds 120 characters (125 chars)
Suggestion: Break long lines into multiple lines for readability

                foreach ($sdkLabel instanceof Method ? [$sdkLabel] : (\is_array($sdkLabel) ? $sdkLabel : []) as $sdkMeth...

[CQ-009] app/controllers/shared/api.php:823 (Style · LOW)

Issue: Line exceeds 120 characters (144 chars)
Suggestion: Break long lines into multiple lines for readability

                    if ($sdkMethod instanceof Method && isset($sdkIndex[$k = $sdkMethod->getNamespace() . '.' . $sdkMeth...

Per-File Breakdown

File Critical High Medium Low Total
app/config/collections/platform.php 0 0 0 1 1
app/controllers/shared/api.php 0 1 2 44 47
app/init/configs.php 0 0 0 1 1
app/init/models.php 0 0 0 1 1
docs/references/projects/list-stages.md 0 0 0 1 1
docs/references/projects/update-stage.md 0 0 0 1 1
src/Appwrite/Platform/Modules/Projects/Http/Stages/Update.php 0 0 0 10 10
src/Appwrite/Platform/Modules/Projects/Http/Stages/XList.php 0 0 0 4 4
src/Appwrite/Utopia/Response/Model/Project.php 0 0 0 1 1
src/Appwrite/Utopia/Response/Model/Stage.php 0 0 0 1 1
tests/e2e/Services/Project/StagesBase.php 0 0 0 12 12

Recommendations

  1. Resolve High severity issues, especially error handling gaps and performance bottlenecks.
  • Run automated tests after applying fixes to verify no regressions.

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.

2 participants