Database Schema
Relevant source files
The following files were used as context for generating this wiki page:
- src/database/models/slack-workspace.model.ts
- src/database/models/jira-config.model.ts
- src/database/models/conversation-state.model.ts
- src/database/models/github-config.model.ts
- src/database/models/hubspot-config.model.ts
- src/database/models/notion-config.model.ts
- src/database/models/okta-config.model.ts
- src/database/models/mcp-connection.model.ts
- src/lib/constants.ts
The database schema for Quix is designed around a central slack_workspaces table, which acts as the primary entity for each installed instance of the application. This multi-tenant architecture allows Quix to manage distinct configurations, credentials, and state for each Slack workspace it is connected to. The schema uses Sequelize as its ORM.
The core design principle is to link all integration-specific configurations and runtime data, such as conversation states, back to a SlackWorkspace record via a foreign key. This ensures data isolation between different workspaces. Sensitive information, such as API tokens and keys, is encrypted before being persisted to the database.
Entity-Relationship Diagram
The following diagram illustrates the primary relationships between the core tables in the Quix database.
This ER diagram shows the central slack_workspaces table and its one-to-one or one-to-many relationships with various integration configuration and state tables.
Sources: src/database/models/slack-workspace.model.ts:88-150, src/database/models/jira-config.model.ts, src/database/models/github-config.model.ts, src/database/models/hubspot-config.model.ts, src/database/models/conversation-state.model.ts, src/database/models/mcp-connection.model.ts
Core Models
SlackWorkspace
This is the central model, representing an individual Slack workspace where the Quix bot is installed. It stores workspace-level information, API credentials, and access control settings.
Sources: src/database/models/slack-workspace.model.ts
| Field | Type | Constraints | Description |
|---|---|---|---|
team_id | STRING | PRIMARY KEY | The unique identifier for the Slack workspace (e.g., T12345678). |
name | STRING | NOT NULL | The name of the Slack workspace. |
bot_access_token | TEXT | NOT NULL, Encrypted | The Slack bot OAuth token for API access. The value is encrypted in the database. |
authed_user_id | STRING | NOT NULL | The ID of the user who installed the app. |
bot_user_id | STRING | NOT NULL | The user ID of the Quix bot in the workspace. |
is_enterprise_install | BOOLEAN | NOT NULL | Flag indicating if this is a Slack Enterprise Grid installation. |
scopes | ARRAY(STRING) | NOT NULL | An array of OAuth scopes granted to the bot. |
app_id | STRING | NOT NULL | The ID of the Slack App. |
domain | STRING | NULLABLE | The domain of the Slack workspace. |
openai_key | TEXT | NULLABLE, Encrypted | The OpenAI API key provided by the user. The value is encrypted. If not set, a default key is used during a trial period. |
admin_user_ids | ARRAY(STRING) | NOT NULL, Default: [] | A list of Slack user IDs who have admin privileges for Quix within the workspace. |
access_settings | JSONB | NOT NULL | JSON object storing access control settings, such as which users can interact with the bot in DMs. |
created_at | DATE | - | Timestamp of when the record was created. |
updated_at | DATE | - | Timestamp of when the record was last updated. |
Access Control
The access_settings field is a JSONB column that controls user permissions. It contains a key allowedUsersForDmInteraction which can have values from the QuixUserAccessLevel enum.
// src/lib/constants.ts:10-13
export enum QuixUserAccessLevel {
ADMINS_ONLY = 'admins_only',
EVERYONE = 'everyone'
}
The SlackWorkspace model includes helper methods to manage and check permissions based on these settings.
Sources: src/database/models/slack-workspace.model.ts:208-232, src/lib/constants.ts:10-13
ConversationState
This table stores the state of ongoing conversations to provide context for multi-turn interactions with the bot. Each record is linked to a specific Slack channel and thread.
Sources: src/database/models/conversation-state.model.ts
| Field | Type | Constraints | Description |
|---|---|---|---|
id | INTEGER | PRIMARY KEY, AUTO_INCREMENT | The unique identifier for the state record. |
team_id | STRING | NOT NULL, FOREIGN KEY | Foreign key referencing slack_workspaces.team_id. |
channel_id | STRING | NOT NULL | The Slack channel ID where the conversation is happening. |
thread_ts | STRING | NOT NULL | The timestamp of the thread, acting as its unique identifier. |
state | JSONB | NOT NULL | A JSON object containing the conversation context, such as previous tool calls or user messages. |
created_at | DATE | - | Timestamp of when the record was created. |
updated_at | DATE | - | Timestamp of when the record was last updated. |
Integration Configuration Models
Quix supports various third-party integrations. The configuration and credentials for each activated integration are stored in separate tables, each having a one-to-one relationship with the slack_workspaces table.
JiraConfig
Stores configuration for the Jira integration.
Sources: src/database/models/jira-config.model.ts
| Field | Type | Constraints | Description |
|---|---|---|---|
id | INTEGER | PRIMARY KEY, AUTO_INCREMENT | Unique identifier for the Jira configuration. |
team_id | STRING | NOT NULL, UNIQUE, FOREIGN KEY | Foreign key referencing slack_workspaces.team_id. |
access_token | TEXT | NOT NULL, Encrypted | The OAuth access token for the Jira API. |
refresh_token | TEXT | NOT NULL, Encrypted | The OAuth refresh token for the Jira API. |
cloud_id | STRING | NOT NULL | The unique cloud ID of the Jira instance. |
user_id | STRING | NOT NULL | The ID of the user who authorized the integration. |
GithubConfig
Stores configuration for the GitHub integration.
Sources: src/database/models/github-config.model.ts
| Field | Type | Constraints | Description |
|---|---|---|---|
id | INTEGER | PRIMARY KEY, AUTO_INCREMENT | Unique identifier for the GitHub configuration. |
team_id | STRING | NOT NULL, UNIQUE, FOREIGN KEY | Foreign key referencing slack_workspaces.team_id. |
access_token | TEXT | NOT NULL, Encrypted | The OAuth access token for the GitHub API. |
user_id | STRING | NOT NULL | The ID of the user who authorized the integration. |
owner | STRING | NULLABLE | Default GitHub owner/organization for repository operations. |
repo | STRING | NULLABLE | Default GitHub repository name. |
Other Integration Configs
Similar configuration tables exist for other supported integrations, all following the same pattern of a one-to-one relationship with slack_workspaces:
HubspotConfig: Stores HubSpot portal ID and OAuth tokens. (Source: src/database/models/hubspot-config.model.ts).NotionConfig: Stores Notion workspace ID and access token. (Source: src/database/models/notion-config.model.ts).OktaConfig: Stores Okta domain and API token. (Source: src/database/models/okta-config.model.ts).PostgresConfig,SalesforceConfig,ZendeskConfig,LinearConfig,JumpCloudConfigare also present and follow a similar structure. (Source: src/database/models/slack-workspace.model.ts:88-150).
McpConnection
This model stores connection details related to the Model Context Protocol (MCP), linking integrations to a specific workspace.
Sources: src/database/models/mcp-connection.model.ts
| Field | Type | Constraints | Description |
|---|---|---|---|
id | INTEGER | PRIMARY KEY, AUTO_INCREMENT | Unique identifier for the MCP connection. |
team_id | STRING | NOT NULL, FOREIGN KEY | Foreign key referencing slack_workspaces.team_id. |
connection_id | STRING | NOT NULL | The unique ID for this connection. |
integration_name | STRING | NOT NULL | The name of the integration (e.g., 'jira', 'github'). |
user_id | STRING | NOT NULL | The ID of the user who created the connection. |
Data Encryption
Sensitive credentials like bot_access_token, openai_key, and integration-specific access_token fields are automatically encrypted and decrypted via getter and setter methods in their respective Sequelize models. This ensures that raw credentials are not stored in plain text in the database.
The encryption/decryption logic is implemented in the model definitions.
// Example from src/database/models/slack-workspace.model.ts:46-56
get bot_access_token(): string {
const value = this.getDataValue('bot_access_token') as string;
if (!value) return value;
return decrypt(value);
}
set bot_access_token(value: string) {
if (!value) {
this.setDataValue('bot_access_token', value);
return;
}
this.setDataValue('bot_access_token', encrypt(value));
}
Sources: src/database/models/slack-workspace.model.ts:46-56, src/database/models/jira-config.model.ts:32-45, src/database/models/github-config.model.ts:29-42