---
title: "Derive Platform Key"
description: "This document outlines the execution flow when a user initiates a \"Test Connection\" action from the Integration Platform Test Page, specifically focusing on the backend process of decrypting stored..."
last_updated: "2026-05-06T07:30:58.159818+00:00"
canonical_url: "https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/how-it-works/derive-platform-key"
---

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [apps/app/src/app/app/orgId/integrations/platform-test/page.tsx](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/integrations/platform-test/page.tsx)
- [apps/api/src/integration-platform/controllers/connections.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/connections.controller.ts)
- [apps/api/src/integration-platform/services/credential-vault.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/credential-vault.service.ts)
</details>

This document outlines the execution flow when a user initiates a "Test Connection" action from the Integration Platform Test Page, specifically focusing on the backend process of decrypting stored credentials. This flow is critical for ensuring that sensitive integration credentials, such as API keys or OAuth tokens, are securely stored and retrieved only when needed, and then correctly decrypted for use by the integration logic.

The process begins with a user interaction on the frontend, triggering an API call to the backend. The backend then retrieves the encrypted credentials from its vault, performs a multi-step decryption process involving key derivation, and finally makes the decrypted credentials available for the connection testing logic. This secure handling of credentials is fundamental to maintaining the integrity and confidentiality of integration data.

### 1. IntegrationPlatformTestPage

The journey begins on the `IntegrationPlatformTestPage`, a React component responsible for displaying and managing integration connections. This page provides a user interface to view available providers, existing connections, and actions like "Test Connection." When a user clicks the "Test" button associated with a specific connection, it initiates the `handleTestConnection` function.

Sources: [apps/app/src/app/(app)/[orgId]/integrations/platform-test/page.tsx:557-557](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/integrations/platform-test/page.tsx#L557-L557)

### 2. handleTestConnection

The `handleTestConnection` function is a client-side asynchronous operation defined within the `IntegrationPlatformTestPage` component. It takes the `connectionId` and `providerSlug` as arguments. Its primary role is to make an API call to the backend to test the specified connection. It uses the `testConnection` mutation provided by the `useIntegrationMutations` hook, which abstracts the actual HTTP request. Upon receiving a response from the API, it logs the success or failure message to the UI's action log and refreshes the list of connections.

Sources: [apps/app/src/app/(app)/[orgId]/integrations/platform-test/page.tsx:590-599](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/integrations/platform-test/page.tsx#L590-L599)

### 3. testConnection

This method is an API endpoint within the `ConnectionsController` on the backend, accessible via a `POST` request to `/v1/integrations/connections/:id/test`. It receives the `connectionId` from the URL parameter. Its responsibility is to orchestrate the connection testing process.

First, it retrieves the connection details from the database. Crucially, it then calls `this.credentialVaultService.getDecryptedCredentials(connection.id)` to fetch and decrypt the sensitive credentials associated with that connection. If no credentials are found, it throws an error. For AWS connections, it delegates to a specific `testAwsConnection` method. For other providers, it attempts to use a `testConnection` handler defined in the integration's manifest. The outcome (success or failure) is then used to update the connection's status in the database.

Sources: [apps/api/src/integration-platform/controllers/connections.controller.ts:608-649](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/connections.controller.ts#L608-L649)

### 4. getDecryptedCredentials

Located in the `CredentialVaultService`, this asynchronous method is responsible for retrieving the latest encrypted credential version for a given `connectionId` and then decrypting its payload. It fetches the `latestVersion` from the `credentialRepository`. If no version is found, it returns `null`.

It then iterates through the `encryptedPayload` of the credential. For each field that is identified as `EncryptedData` (meaning it contains `encrypted`, `iv`, `tag`, and `salt` properties), it calls `this.decrypt(value)` to obtain the plaintext string. Other fields (like `token_type` or `scope` for OAuth) are returned as-is. Array values are also handled, with each encrypted item within the array being decrypted individually. The method returns a `Record` containing all the decrypted credential values.

Sources: [apps/api/src/integration-platform/services/credential-vault.service.ts:182-215](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/credential-vault.service.ts#L182-L215)

### 5. decrypt

This is the core decryption method within the `CredentialVaultService`. It takes an `EncryptedData` object as input, which contains the base64-encoded encrypted text, initialization vector (IV), authentication tag, and salt.

The method first retrieves the master `SECRET_KEY` from environment variables. It then converts the base64-encoded components (encrypted text, IV, tag, salt) back into Node.js `Buffer` objects. The crucial step here is calling `this.deriveKey(secretKey, salt)` to generate the symmetric decryption key. With the derived key, IV, and tag, it initializes a `createDecipheriv` cipher, updates it with the encrypted data, and finalizes the decryption. The resulting plaintext is returned as a UTF-8 string.

Sources: [apps/api/src/integration-platform/services/credential-vault.service.ts:74-89](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/credential-vault.service.ts#L74-L89)

### 6. deriveKey

The `deriveKey` method, also part of the `CredentialVaultService`, is responsible for securely generating a cryptographic key from a secret and a salt. It uses Node.js's `crypto.scryptSync` function, a password-based key derivation function (PBKDF) designed to be computationally intensive, thus making brute-force attacks more difficult.

It takes the master `secret` (the `SECRET_KEY` from environment variables) and a `salt` (randomly generated for each encryption) as input. It then applies `scryptSync` with specific parameters: `N` (CPU/memory cost factor), `r` (block size), and `p` (parallelization factor), and requests a `KEY_LENGTH` of 32 bytes. The output is a `Buffer` containing the derived key, which is then used by the `decrypt` method for the actual decryption process.

Sources: [apps/api/src/integration-platform/services/credential-vault.service.ts:68-72](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/credential-vault.service.ts#L68-L72)

### Sequence Diagram

```mermaid
sequenceDiagram
    participant UI as IntegrationPlatformTestPage
    participant Client as handleTestConnection
    participant API as ConnectionsController
    participant VaultService as CredentialVaultService

    UI->>Client: User clicks "Test Connection" (connectionId, providerSlug)
    Client->>API: POST /v1/integrations/connections/:id/test
    API->>VaultService: getDecryptedCredentials(connectionId)
    VaultService->>VaultService: findLatestByConnection(connectionId)
    alt Credential found
        loop For each encrypted field in payload
            VaultService->>VaultService: decrypt(encryptedData)
            VaultService->>VaultService: getSecretKey()
            VaultService->>VaultService: deriveKey(secretKey, salt)
            VaultService-->>VaultService: Derived Key
            VaultService-->>VaultService: Decrypted Value
        end
        VaultService-->>API: Decrypted Credentials (Record<string, string | string[]>)
        API->>API: Perform connection test logic (e.g., validateAwsCredentials)
        API-->>Client: Test Result (success/failure message)
    else No credential found
        VaultService-->>API: null
        API-->>Client: Error: No credentials found
    end
    Client-->>UI: Update UI with test result/error
```

### Flowchart



### Key Observations

*   **Cross-Module Boundaries**: The execution flow spans significant architectural layers, starting from the Next.js frontend (`IntegrationPlatformTestPage`), crossing the network boundary to the NestJS API gateway (`ConnectionsController`), and then delving into a dedicated backend service (`CredentialVaultService`) for secure credential handling. This clear separation of concerns enhances maintainability and security.
*   **Potential Failure Points**:
    *   **Missing `SECRET_KEY`**: The `getSecretKey` method explicitly checks for the `SECRET_KEY` environment variable. If this critical key is not set, the application will crash during decryption attempts, rendering all encrypted credentials unusable.
    *   **Corrupted Encrypted Data**: If any part of the `EncryptedData` (encrypted text, IV, tag, salt) is corrupted or tampered with, the decryption process will fail, likely resulting in an `Authentication Tag Mismatch` error, indicating data integrity compromise.
    *   **Incorrect `SECRET_KEY`**: If the `SECRET_KEY` used for decryption does not match the one used for encryption, the `deriveKey` function will produce a different key, leading to decryption failure.
    *   **Database Issues**: Problems fetching the latest credential version from the `credentialRepository` would prevent decryption.
    *   **Network Errors**: The initial API call from the client to the controller could fail due to network connectivity issues.
*   **Performance Considerations**: The `deriveKey` method uses `scryptSync`, a computationally intensive key derivation function. While this is excellent for security (making brute-force attacks harder), its synchronous nature means it blocks the Node.js event loop during execution. For a single connection test, this overhead is acceptable. However, in scenarios requiring high-volume, concurrent decryption operations, this could become a performance bottleneck. The parameters (`N`, `r`, `p`) for `scryptSync` are chosen to provide a balance between security and acceptable performance.
*   **Security Best Practices**: The use of `scryptSync` with a unique `salt` for each encryption, along with AES-256-GCM (which provides authenticated encryption), demonstrates robust cryptographic practices for protecting sensitive data at rest. The separation of the master secret key (`SECRET_KEY`) from the application code and its reliance on environment variables is also a good security practice.

## Sitemap

See the full [sitemap](https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/llms.txt) for all pages in this wiki.
