Skip to content

Conversation

@Meldiron
Copy link
Contributor

@Meldiron Meldiron commented Dec 22, 2025

What does this PR do?

Implements UI to manage more types of keys

Test Plan

Manual QA

Related PRs and Issues

appwrite/appwrite#10988

Have you read the Contributing Guidelines on issues?

Yes

Summary by CodeRabbit

Release Notes

  • New Features
    • Added account integrations section with API key management.
    • Added organization integrations section with key management (Applications and Installations coming soon).
    • Extended key management system to support organization and account tokens in addition to API keys.
    • Added keyboard shortcuts to navigate to integrations pages.

✏️ Tip: You can customize this high-level summary in your review settings.

@appwrite
Copy link

appwrite bot commented Dec 22, 2025

Console (appwrite/console)

Project ID: 688b7bf400350cbd60e9

Sites (1)
Site Status Logs Preview QR
 console-stage
688b7cf6003b1842c9dc
Ready Ready View Logs Preview URL QR Code

Tip

Global CDN and DDoS protection come free with every Sites deployment

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 22, 2025

Walkthrough

This PR extends the application to support organizational and account-level API keys alongside existing API keys. Changes include: updating the scopes data structure with a new type field ('api' | 'organization' | 'account') and adding corresponding scope entries; creating new routes and pages for account and organization integrations; refactoring key management components (create, delete, table) to handle multiple key types; updating navigation headers with integrations tabs; and modifying the scopes component to filter based on key type. The dependency @appwrite.io/console is also updated to a newer artifact version.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

  • Scopes data structure expansion: Review the new type field additions across scopes and cloudOnlyBackupScopes entries to ensure all entries are correctly classified and no values are missing.
  • create.svelte refactoring: Verify the type-specific key creation flows (createProjectKey, createOrganizationKey, createAccountKey) properly delegate to correct SDK methods, handle invalidation correctly, and navigate to appropriate routes for each type.
  • table.svelte helper functions: Check that the new derived helper functions (canWrite, getLabel, getSlug, getColumns, etc.) correctly map behavior for all four key types and that conditional rendering (scopes, create button) uses correct predicates.
  • deleteBatch.svelte deletion logic: Ensure deleteKey properly routes to the correct SDK endpoint for each key type and that postDeleteRedirect behaves correctly (API keys navigate; others are no-ops).
  • scopes.svelte filtering: Verify the new type-based filtering pipeline correctly filters scope entries and that category computation dynamically derives from filtered scopes.
  • Route consistency: Confirm that new routes (account/integrations, organization/integrations) properly load and pass data, and that navigation commands/tabs correctly enable/disable based on conditions.
  • SDK integration: Verify all new SDK calls (sdk.forConsole.account.listKeys, sdk.forConsole.organizations.listKeys) are correctly invoked with proper parameters.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Feat: Organization & account keys' accurately captures the main feature being implemented—support for managing organization and account key types alongside existing API keys.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat-platform-keys

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

Comment @coderabbitai help to get the list of available commands and usage tips.

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: 2

🧹 Nitpick comments (5)
src/routes/(console)/account/integrations/create-token/+page.svelte (1)

1-5: Use $routes alias instead of deep relative path.

The import uses a fragile 3-level relative path. As per coding guidelines, prefer $routes alias for route module imports.

Suggested fix
 <script lang="ts">
-    import CreateKey from '../../../project-[region]-[project]/overview/(components)/create.svelte';
+    import CreateKey from '$routes/(console)/project-[region]-[project]/overview/(components)/create.svelte';
 </script>
src/routes/(console)/account/integrations/+page.svelte (1)

1-11: Consider migrating to Svelte 5 runes syntax.

The component uses Svelte 4's export let data pattern. Other files in this PR (e.g., header.svelte) use Svelte 5's $derived rune. Consider using Svelte 5 syntax for consistency.

Svelte 5 runes syntax
 <script lang="ts">
     import { Container } from '$lib/layout';
     import type { PageData } from './$types';
     import Keys from './keys.svelte';
 
-    export let data: PageData;
+    let { data }: { data: PageData } = $props();
 </script>
src/routes/(console)/organization-[organization]/integrations/create-key/+page.svelte (1)

2-2: Consider moving shared CreateKey component to $lib for better maintainability.

The relative import path traverses multiple directory levels to access a component from a different route section. This creates tight coupling and violates the coding guideline to use $lib alias instead of relative paths.

🔎 Recommended approach

Move the shared CreateKey component to $lib/components or a similar shared location, then import it using the $lib alias:

-    import CreateKey from '../../../project-[region]-[project]/overview/(components)/create.svelte';
+    import CreateKey from '$lib/components/createKey.svelte';

This improves maintainability and follows the project's convention of using path aliases.

Based on coding guidelines: Use $lib, $routes, and $themes aliases instead of relative paths for module imports.

src/routes/(console)/organization-[organization]/integrations/keys.svelte (1)

5-5: Consider moving shared Table component to $lib.

Similar to the CreateKey component, the Table component is imported using a relative path from a different route section. For consistency and maintainability, shared components should be placed in $lib and imported using the $lib alias.

Based on coding guidelines: Use $lib, $routes, and $themes aliases instead of relative paths for module imports.

src/routes/(console)/account/integrations/keys.svelte (1)

5-5: Consider moving shared Table component to $lib.

The Table component is imported using a relative path from a different route section. For consistency and maintainability, shared components should be placed in $lib and imported using the $lib alias.

Based on coding guidelines: Use $lib, $routes, and $themes aliases instead of relative paths for module imports.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 580e5bf and 87a473e.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (20)
  • package.json
  • src/lib/constants.ts
  • src/routes/(console)/account/header.svelte
  • src/routes/(console)/account/integrations/+page.svelte
  • src/routes/(console)/account/integrations/+page.ts
  • src/routes/(console)/account/integrations/create-token/+page.svelte
  • src/routes/(console)/account/integrations/keys.svelte
  • src/routes/(console)/organization-[organization]/+layout.svelte
  • src/routes/(console)/organization-[organization]/header.svelte
  • src/routes/(console)/organization-[organization]/integrations/+page.svelte
  • src/routes/(console)/organization-[organization]/integrations/+page.ts
  • src/routes/(console)/organization-[organization]/integrations/apps.svelte
  • src/routes/(console)/organization-[organization]/integrations/create-key/+page.svelte
  • src/routes/(console)/organization-[organization]/integrations/installations.svelte
  • src/routes/(console)/organization-[organization]/integrations/keys.svelte
  • src/routes/(console)/project-[region]-[project]/overview/(components)/create.svelte
  • src/routes/(console)/project-[region]-[project]/overview/(components)/deleteBatch.svelte
  • src/routes/(console)/project-[region]-[project]/overview/(components)/table.svelte
  • src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte
  • src/routes/(console)/project-[region]-[project]/overview/store.ts
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx,js,jsx,svelte}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx,svelte}: Import reusable modules from the src/lib directory using the $lib alias
Use minimal comments in code; reserve comments for TODOs or complex logic explanations
Use $lib, $routes, and $themes aliases instead of relative paths for module imports

Files:

  • src/routes/(console)/account/integrations/+page.svelte
  • src/routes/(console)/account/integrations/+page.ts
  • src/routes/(console)/organization-[organization]/integrations/keys.svelte
  • src/routes/(console)/organization-[organization]/integrations/installations.svelte
  • src/routes/(console)/project-[region]-[project]/overview/(components)/create.svelte
  • src/routes/(console)/organization-[organization]/integrations/+page.ts
  • src/routes/(console)/organization-[organization]/integrations/apps.svelte
  • src/routes/(console)/project-[region]-[project]/overview/store.ts
  • src/routes/(console)/project-[region]-[project]/overview/(components)/deleteBatch.svelte
  • src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte
  • src/routes/(console)/organization-[organization]/integrations/create-key/+page.svelte
  • src/routes/(console)/project-[region]-[project]/overview/(components)/table.svelte
  • src/routes/(console)/account/integrations/create-token/+page.svelte
  • src/routes/(console)/organization-[organization]/+layout.svelte
  • src/routes/(console)/organization-[organization]/header.svelte
  • src/routes/(console)/account/header.svelte
  • src/routes/(console)/organization-[organization]/integrations/+page.svelte
  • src/routes/(console)/account/integrations/keys.svelte
  • src/lib/constants.ts
src/routes/**/*.svelte

📄 CodeRabbit inference engine (AGENTS.md)

Use SvelteKit file conventions: +page.svelte for components, +page.ts for data loaders, +layout.svelte for wrappers, +error.svelte for error handling, and dynamic route params in square brackets like [param]

Files:

  • src/routes/(console)/account/integrations/+page.svelte
  • src/routes/(console)/organization-[organization]/integrations/keys.svelte
  • src/routes/(console)/organization-[organization]/integrations/installations.svelte
  • src/routes/(console)/project-[region]-[project]/overview/(components)/create.svelte
  • src/routes/(console)/organization-[organization]/integrations/apps.svelte
  • src/routes/(console)/project-[region]-[project]/overview/(components)/deleteBatch.svelte
  • src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte
  • src/routes/(console)/organization-[organization]/integrations/create-key/+page.svelte
  • src/routes/(console)/project-[region]-[project]/overview/(components)/table.svelte
  • src/routes/(console)/account/integrations/create-token/+page.svelte
  • src/routes/(console)/organization-[organization]/+layout.svelte
  • src/routes/(console)/organization-[organization]/header.svelte
  • src/routes/(console)/account/header.svelte
  • src/routes/(console)/organization-[organization]/integrations/+page.svelte
  • src/routes/(console)/account/integrations/keys.svelte
**/*.{ts,tsx,js,jsx,svelte,json}

📄 CodeRabbit inference engine (AGENTS.md)

Use 4 spaces for indentation, single quotes, 100 character line width, and no trailing commas per Prettier configuration

Files:

  • src/routes/(console)/account/integrations/+page.svelte
  • src/routes/(console)/account/integrations/+page.ts
  • src/routes/(console)/organization-[organization]/integrations/keys.svelte
  • src/routes/(console)/organization-[organization]/integrations/installations.svelte
  • src/routes/(console)/project-[region]-[project]/overview/(components)/create.svelte
  • src/routes/(console)/organization-[organization]/integrations/+page.ts
  • src/routes/(console)/organization-[organization]/integrations/apps.svelte
  • src/routes/(console)/project-[region]-[project]/overview/store.ts
  • src/routes/(console)/project-[region]-[project]/overview/(components)/deleteBatch.svelte
  • package.json
  • src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte
  • src/routes/(console)/organization-[organization]/integrations/create-key/+page.svelte
  • src/routes/(console)/project-[region]-[project]/overview/(components)/table.svelte
  • src/routes/(console)/account/integrations/create-token/+page.svelte
  • src/routes/(console)/organization-[organization]/+layout.svelte
  • src/routes/(console)/organization-[organization]/header.svelte
  • src/routes/(console)/account/header.svelte
  • src/routes/(console)/organization-[organization]/integrations/+page.svelte
  • src/routes/(console)/account/integrations/keys.svelte
  • src/lib/constants.ts
**/*.svelte

📄 CodeRabbit inference engine (AGENTS.md)

Use Svelte 5 + SvelteKit 2 syntax with TypeScript for component development

Files:

  • src/routes/(console)/account/integrations/+page.svelte
  • src/routes/(console)/organization-[organization]/integrations/keys.svelte
  • src/routes/(console)/organization-[organization]/integrations/installations.svelte
  • src/routes/(console)/project-[region]-[project]/overview/(components)/create.svelte
  • src/routes/(console)/organization-[organization]/integrations/apps.svelte
  • src/routes/(console)/project-[region]-[project]/overview/(components)/deleteBatch.svelte
  • src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte
  • src/routes/(console)/organization-[organization]/integrations/create-key/+page.svelte
  • src/routes/(console)/project-[region]-[project]/overview/(components)/table.svelte
  • src/routes/(console)/account/integrations/create-token/+page.svelte
  • src/routes/(console)/organization-[organization]/+layout.svelte
  • src/routes/(console)/organization-[organization]/header.svelte
  • src/routes/(console)/account/header.svelte
  • src/routes/(console)/organization-[organization]/integrations/+page.svelte
  • src/routes/(console)/account/integrations/keys.svelte
src/routes/**

📄 CodeRabbit inference engine (AGENTS.md)

Configure dynamic routes using SvelteKit convention with [param] syntax in route directory names

Files:

  • src/routes/(console)/account/integrations/+page.svelte
  • src/routes/(console)/account/integrations/+page.ts
  • src/routes/(console)/organization-[organization]/integrations/keys.svelte
  • src/routes/(console)/organization-[organization]/integrations/installations.svelte
  • src/routes/(console)/project-[region]-[project]/overview/(components)/create.svelte
  • src/routes/(console)/organization-[organization]/integrations/+page.ts
  • src/routes/(console)/organization-[organization]/integrations/apps.svelte
  • src/routes/(console)/project-[region]-[project]/overview/store.ts
  • src/routes/(console)/project-[region]-[project]/overview/(components)/deleteBatch.svelte
  • src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte
  • src/routes/(console)/organization-[organization]/integrations/create-key/+page.svelte
  • src/routes/(console)/project-[region]-[project]/overview/(components)/table.svelte
  • src/routes/(console)/account/integrations/create-token/+page.svelte
  • src/routes/(console)/organization-[organization]/+layout.svelte
  • src/routes/(console)/organization-[organization]/header.svelte
  • src/routes/(console)/account/header.svelte
  • src/routes/(console)/organization-[organization]/integrations/+page.svelte
  • src/routes/(console)/account/integrations/keys.svelte
**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/*.ts: Define types inline or in .d.ts files, avoid creating separate .types.ts files
Use TypeScript in non-strict mode; any type is tolerated in this project

Files:

  • src/routes/(console)/account/integrations/+page.ts
  • src/routes/(console)/organization-[organization]/integrations/+page.ts
  • src/routes/(console)/project-[region]-[project]/overview/store.ts
  • src/lib/constants.ts
🧠 Learnings (10)
📚 Learning: 2025-11-25T03:15:27.539Z
Learnt from: CR
Repo: appwrite/console PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T03:15:27.539Z
Learning: Applies to src/routes/**/*.svelte : Use SvelteKit file conventions: +page.svelte for components, +page.ts for data loaders, +layout.svelte for wrappers, +error.svelte for error handling, and dynamic route params in square brackets like [param]

Applied to files:

  • src/routes/(console)/account/integrations/+page.svelte
  • src/routes/(console)/account/integrations/+page.ts
  • src/routes/(console)/organization-[organization]/integrations/keys.svelte
  • src/routes/(console)/organization-[organization]/integrations/installations.svelte
  • src/routes/(console)/organization-[organization]/integrations/apps.svelte
  • src/routes/(console)/project-[region]-[project]/overview/(components)/deleteBatch.svelte
  • src/routes/(console)/organization-[organization]/integrations/create-key/+page.svelte
  • src/routes/(console)/project-[region]-[project]/overview/(components)/table.svelte
  • src/routes/(console)/account/integrations/create-token/+page.svelte
  • src/routes/(console)/account/header.svelte
  • src/routes/(console)/organization-[organization]/integrations/+page.svelte
  • src/routes/(console)/account/integrations/keys.svelte
📚 Learning: 2025-11-25T03:15:27.539Z
Learnt from: CR
Repo: appwrite/console PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T03:15:27.539Z
Learning: Applies to **/*.svelte : Use Svelte 5 + SvelteKit 2 syntax with TypeScript for component development

Applied to files:

  • src/routes/(console)/account/integrations/+page.svelte
  • src/routes/(console)/organization-[organization]/integrations/apps.svelte
  • src/routes/(console)/project-[region]-[project]/overview/(components)/deleteBatch.svelte
  • src/routes/(console)/organization-[organization]/integrations/create-key/+page.svelte
  • src/routes/(console)/account/integrations/create-token/+page.svelte
📚 Learning: 2025-10-05T09:41:40.439Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2398
File: src/routes/(console)/verify-email/+page.svelte:48-51
Timestamp: 2025-10-05T09:41:40.439Z
Learning: In SvelteKit 5, `page` imported from `$app/state` is a reactive state object (using runes), not a store. It should be accessed as `page.data` without the `$` prefix, unlike the store-based `$page` from `$app/stores` in earlier versions.

Applied to files:

  • src/routes/(console)/account/integrations/+page.svelte
  • src/routes/(console)/organization-[organization]/integrations/+page.svelte
📚 Learning: 2025-10-13T05:13:54.542Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2413
File: src/routes/(console)/project-[region]-[project]/databases/table.svelte:33-39
Timestamp: 2025-10-13T05:13:54.542Z
Learning: In Svelte 5, `import { page } from '$app/state'` provides a reactive state proxy that can be accessed directly (e.g., `page.params`), unlike the older `import { page } from '$app/stores'` which returns a readable store requiring the `$page` syntax for auto-subscription in components.

Applied to files:

  • src/routes/(console)/account/integrations/+page.svelte
  • src/routes/(console)/organization-[organization]/integrations/+page.svelte
📚 Learning: 2025-10-13T05:16:07.656Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2413
File: src/routes/(console)/project-[region]-[project]/databases/database-[database]/header.svelte:54-58
Timestamp: 2025-10-13T05:16:07.656Z
Learning: In SvelteKit apps, shared layout components (like headers) that use `$derived(page.data.*)` should use optional chaining when accessing properties that may not be present on all routes. During page transitions, reactive statements can briefly evaluate with different page.data structures, so optional chaining prevents runtime errors when navigating between routes with different data shapes (e.g., between `/databases` and `/databases/database-[database]`).

Applied to files:

  • src/routes/(console)/account/integrations/+page.svelte
  • src/routes/(console)/account/header.svelte
  • src/routes/(console)/organization-[organization]/integrations/+page.svelte
📚 Learning: 2025-11-19T11:22:42.553Z
Learnt from: atharvadeosthale
Repo: appwrite/console PR: 2512
File: src/routes/(console)/project-[region]-[project]/overview/platforms/llmBanner.svelte:51-83
Timestamp: 2025-11-19T11:22:42.553Z
Learning: In src/routes/(console)/project-[region]-[project]/overview/platforms/llmBanner.svelte, the Lovable integration URL format `https://lovable.dev/` with `autosubmit` and `prompt` as query parameters (set via searchParams) is correct and functional.

Applied to files:

  • src/routes/(console)/organization-[organization]/integrations/installations.svelte
  • src/routes/(console)/account/integrations/create-token/+page.svelte
📚 Learning: 2025-11-25T03:15:27.539Z
Learnt from: CR
Repo: appwrite/console PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T03:15:27.539Z
Learning: Applies to src/lib/components/**/*.svelte : Use PascalCase for component file names and place them in src/lib/components/[feature]/ directory structure

Applied to files:

  • src/routes/(console)/organization-[organization]/integrations/apps.svelte
  • src/routes/(console)/organization-[organization]/integrations/+page.svelte
📚 Learning: 2025-09-26T06:48:57.938Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2373
File: src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/empty.svelte:629-631
Timestamp: 2025-09-26T06:48:57.938Z
Learning: In the Appwrite console codebase using appwrite.io/pink-svelte, the Icon component automatically handles CSS variable names passed to its color prop by internally wrapping them with var(). Therefore, passing '--some-css-variable' as a string to the Icon color prop works correctly without needing to manually wrap it with var().

Applied to files:

  • package.json
📚 Learning: 2025-09-30T07:41:06.679Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2425
File: src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/empty.svelte:454-468
Timestamp: 2025-09-30T07:41:06.679Z
Learning: In `src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/empty.svelte`, the column suggestions API (console.suggestColumns) has a maximum limit of 7 columns returned, which aligns with the initial placeholder count of 7 in customColumns.

Applied to files:

  • src/routes/(console)/project-[region]-[project]/overview/(components)/table.svelte
📚 Learning: 2025-11-19T11:22:42.553Z
Learnt from: atharvadeosthale
Repo: appwrite/console PR: 2512
File: src/routes/(console)/project-[region]-[project]/overview/platforms/llmBanner.svelte:51-83
Timestamp: 2025-11-19T11:22:42.553Z
Learning: In src/routes/(console)/project-[region]-[project]/overview/platforms/llmBanner.svelte, the Cursor integration URL format `https://cursor.com/link/prompt` with the `text` query parameter is correct and functional.

Applied to files:

  • src/routes/(console)/account/integrations/create-token/+page.svelte
🧬 Code graph analysis (3)
src/routes/(console)/account/integrations/+page.ts (2)
src/routes/(console)/organization-[organization]/integrations/+page.ts (1)
  • load (5-16)
src/lib/stores/sdk.ts (1)
  • sdk (173-196)
src/routes/(console)/organization-[organization]/integrations/+page.ts (2)
src/routes/(console)/account/integrations/+page.ts (1)
  • load (5-15)
src/lib/stores/sdk.ts (1)
  • sdk (173-196)
src/routes/(console)/project-[region]-[project]/overview/store.ts (1)
src/lib/helpers/types.ts (1)
  • Column (44-61)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: e2e
🔇 Additional comments (22)
package.json (1)

25-25: LGTM - SDK dependency update.

The updated @appwrite.io/console artifact is required for the new account.listKeys() and organizations.listKeys() SDK methods used by this feature.

Ensure the new SDK artifact (b369c68) includes the account.listKeys and organizations.listKeys methods referenced in the new integration pages.

src/routes/(console)/account/integrations/+page.ts (1)

1-15: LGTM - Data loader follows established patterns.

The loader correctly mirrors the organization integrations loader structure, uses appropriate dependency tracking, and properly returns the keys data.

src/routes/(console)/organization-[organization]/integrations/installations.svelte (1)

1-23: LGTM - Clean placeholder component.

The installations component follows the established CardGrid pattern and appropriately indicates the feature is coming soon.

src/routes/(console)/account/header.svelte (1)

14-53: Good refactoring to unified tabs pattern.

The declarative approach with a filtered array is cleaner than conditional array composition. The new Integrations tab is correctly configured as cloud-only with hasChildren: true for sub-routes.

src/lib/constants.ts (2)

159-165: Well-structured type extension for scopes.

The addition of the type discriminator field enables proper filtering of scopes based on key context (API, organization, or account). This is a clean approach to extending the data model.


599-613: No action required. Scope filtering by type is already correctly implemented in the Scopes component (scopes.svelte) with the explicit filter .filter((scope) => scope.type === type), preventing duplicate scope names from appearing in the UI.

src/routes/(console)/organization-[organization]/header.svelte (1)

87-92: LGTM! Integrations tab follows established patterns.

The new Integrations tab is properly configured with appropriate access controls (owner-only and cloud-only), consistent with the existing tab structure.

src/routes/(console)/organization-[organization]/+layout.svelte (1)

39-47: LGTM! Navigation command properly configured.

The new "Go to integrations" command follows the established pattern with appropriate keyboard shortcuts and access controls.

src/routes/(console)/organization-[organization]/integrations/apps.svelte (1)

14-21: Verify placeholder content is intentional.

The "Coming soon" message indicates this feature is in testing. Confirm this placeholder is appropriate for the current release and whether tracking exists for when this will be implemented.

src/routes/(console)/organization-[organization]/integrations/+page.svelte (1)

1-15: LGTM! Clean component composition.

The page follows SvelteKit conventions and cleanly composes the integrations UI sections. The data flow from the load function to child components is straightforward and type-safe.

src/routes/(console)/organization-[organization]/integrations/+page.ts (1)

8-11: No issues found. The SDK method sdk.forConsole.organizations.listKeys is correctly called with the appropriate parameters organizationId and total. The route parameter params.organization correctly contains the organization ID from the [organization] dynamic route segment per SvelteKit convention.

src/routes/(console)/project-[region]-[project]/overview/store.ts (1)

41-43: LGTM!

The new column presets for organization and account keys are correctly defined and follow the established pattern of cloning keyColumns. The implementation is consistent with how devKeyColumns is structured.

src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte (2)

37-37: LGTM!

The new type prop correctly enables filtering scopes by resource type (api/organization/account), supporting the multi-scope key management feature.


51-59: LGTM!

The type-based filtering logic correctly narrows scopes to match the specified key type, ensuring users only see relevant permissions for API, organization, or account keys.

src/routes/(console)/project-[region]-[project]/overview/(components)/deleteBatch.svelte (1)

20-111: Well-structured refactor with consistent helper functions.

The helper functions (getLabel, getSlug, getEvent, getDependency, deleteKey, postDeleteRedirect) effectively centralize key-type-specific logic, making the code maintainable and reducing duplication.

However, verify the following:

  1. Event tracking: getEvent() returns Submit.KeyDelete for api, organization, and account keys. Confirm whether separate analytics events are needed to distinguish between these key types.
  2. Post-deletion navigation: postDeleteRedirect() only navigates for API keys (lines 98-101), while other types remain on the same page. Verify this is the intended UX.
src/routes/(console)/project-[region]-[project]/overview/(components)/create.svelte (3)

21-21: LGTM!

The type prop correctly enables the component to handle creation of API keys, organization keys, and account tokens with a single unified interface.


33-79: Clean separation of key creation logic.

The three specialized creation functions (createProjectKey, createOrganizationKey, createAccountKey) properly handle:

  • Type-specific SDK calls
  • Appropriate dependency invalidation
  • Correct navigation to the resource-specific path

The implementation is well-organized and maintainable.


98-122: Dynamic notification with smart copy actions.

The notification logic correctly:

  • Generates a resource-specific title (line 98-99)
  • Always includes a copy button for the key/token (lines 100-107)
  • Conditionally adds "Copy endpoint" only for API keys (lines 109-116)

This provides a better UX by tailoring the notification to each key type.

src/routes/(console)/project-[region]-[project]/overview/(components)/table.svelte (4)

38-49: Correct permission checks per key type.

The canWrite() function appropriately maps each key type to its corresponding permission:

  • API keys → $canWriteKeys
  • Dev keys → $canWriteProjects
  • Organization keys → $canWriteTeams
  • Account tokens → true (user always has permission for their own account)

This ensures proper access control for each resource type.


51-156: Well-designed helper functions for multi-type support.

The helper functions (getLabel, getSlug, getColumns, getExpiredColor, getDescription, hasScopes) effectively centralize type-specific behavior, making the component:

  • Maintainable: All type-specific logic is in one place
  • Extensible: Adding new key types requires updating helpers in a predictable way
  • DRY: Eliminates repeated conditionals throughout the template

The implementation correctly handles nuances like:

  • Dev keys don't have scopes (line 147-156)
  • Different expiration colors for dev keys vs. others (line 90-99)
  • Appropriate column presets for each type (line 77-88)

158-177: Smart navigation logic per key type.

The onKeyCreate() function correctly:

  • Routes to project-specific creation for API keys (lines 161-163)
  • Routes to organization integration for organization keys (lines 166-168)
  • Routes to account integration for account tokens (lines 170-171)
  • Opens a modal for dev keys instead of navigation (line 174)

This aligns with the different UX flows for each key type.


249-256: Conditional create button with correct visibility logic.

The create button:

  • Only renders when showCreateButton is true AND keys exist (line 249)
  • Uses the appropriate label for the key type (line 253)
  • Triggers the correct creation flow via onKeyCreate() (line 251)

This provides flexible control over when the create action is shown.

Comment on lines +592 to +598
{
scope: 'account',
description: "Access to manage account, it's organizations, sessions, tokens, and billing.",
category: 'Other',
icon: 'globe',
type: 'account'
},
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 | 🟡 Minor

Minor: Grammar fix needed in description.

"it's" is a contraction of "it is". Use "its" (possessive) instead.

Suggested fix
     {
         scope: 'account',
-        description: "Access to manage account, it's organizations, sessions, tokens, and billing.",
+        description: "Access to manage account, its organizations, sessions, tokens, and billing.",
         category: 'Other',
         icon: 'globe',
         type: 'account'
     },
📝 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
{
scope: 'account',
description: "Access to manage account, it's organizations, sessions, tokens, and billing.",
category: 'Other',
icon: 'globe',
type: 'account'
},
{
scope: 'account',
description: "Access to manage account, its organizations, sessions, tokens, and billing.",
category: 'Other',
icon: 'globe',
type: 'account'
},
🤖 Prompt for AI Agents
In src/lib/constants.ts around lines 592 to 598, the description text uses the
contraction "it's" incorrectly; change "it's organizations, sessions, tokens,
and billing." to the possessive form "its organizations, sessions, tokens, and
billing." so the description reads: "Access to manage account, its
organizations, sessions, tokens, and billing."

return !legacyPrefixes.some((prefix) => val.startsWith(prefix));
});
console.log(baseFilteredScopes);
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 | 🟡 Minor

Remove debug logging.

This console.log statement appears to be leftover debug code and should be removed before merging.

🔎 Proposed fix
-    console.log(baseFilteredScopes);
-
     // insert cloud-only scopes right after databases.write
📝 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
console.log(baseFilteredScopes);
// insert cloud-only scopes right after databases.write
🤖 Prompt for AI Agents
In
src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte
around line 47 there is a leftover debug statement
`console.log(baseFilteredScopes);`; remove this console.log call (and any other
stray debug logging if present) so no debugging output remains in production
code, and run lint/format to ensure the file compiles cleanly after removal.

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