diff --git a/sqlite-cloud/_nav.ts b/sqlite-cloud/_nav.ts index ec1fb7b..5093215 100644 --- a/sqlite-cloud/_nav.ts +++ b/sqlite-cloud/_nav.ts @@ -287,7 +287,8 @@ const sidebarNav: SidebarNavStruct = [ { title: "Webhooks", filePath: "webhooks", type: "inner", level: 0 }, { title: "Pub/Sub", filePath: "pub-sub", type: "inner", level: 0 }, //{ title: "Vector", filePath: "vector", type: "inner", level: 0 }, - { title: "Users and Roles", filePath: "security", type: "inner", level: 0 }, + { title: "Users", filePath: "users", type: "inner", level: 0 }, + { title: "Roles & Privileges", filePath: "roles", type: "inner", level: 0 }, { title: "API Keys", filePath: "apikey", type: "inner", level: 0 }, { title: "Row-Level Security", filePath: "rls", type: "inner", level: 0 }, { title: "OffSync", filePath: "offsync", type: "inner", level: 0 }, diff --git a/sqlite-cloud/platform/apikey.mdx b/sqlite-cloud/platform/apikey.mdx index 87a5a97..3b83061 100644 --- a/sqlite-cloud/platform/apikey.mdx +++ b/sqlite-cloud/platform/apikey.mdx @@ -1,20 +1,75 @@ --- title: Security and Access Control -description: SQLite Cloud provides secure access to resources through role-based authorization, which ensures user isolation and enhances security and manageability. +description: Manage API Keys for secure application access, server-to-server communication, and SDK integration. category: platform status: publish slug: apikey --- -## API KEYs API KEYs can be used as an alternative authentication mechanism. Authentication through API keys ensures the same privileges as the user to which they are associated. API KEYs are recommended for all server-to-server authentication cases and are necessary for using the REST APIs and the SDKs that uses the WebSocket APIs. -To create an API key for a user, click on the **Create API KEY** button. +You can manage all keys in your cluster via the SQLite Cloud Dashboard under the **API Keys** section. -![Dashboard Create APIKEY](@docs-website-assets/introduction/dashboard_create_apikey.png) +--- + +## Creating an API Key + +You can create an API Key and immediately assign it to any existing user in your cluster. + +1. Navigate to the **API Keys** section in the left sidebar. +2. Click the **Create API Key** button. +3. **API Key Name:** Enter a descriptive name to identify the key (e.g., `MobileApp_Prod`, `Backend_Worker`). +4. **User:** Select the user this key will impersonate from the dropdown list. +5. **Expiration:** + * Select **Never expires** for long-running services. + * Select **Set expiration date** to enforce a rotation policy or for temporary access tokens. +6. Click **Create**. + +[VIDEO: create_apikey_global.mp4] +{/* */} + +--- + +## Managing API Keys + +The API Keys list provides a centralized view of all active keys, their associated users, and expiration status. + +### Regenerating a Key +If a key is lost, forgotten, or you suspect it has been compromised (leaked), you should regenerate it immediately. + +1. Find the key in the list. +2. Click the context menu (three dots) on the right. +3. Select **Regenerate**. +4. Confirm the action in the modal window. + +**Warning:** Regenerating a key invalidates the old key string immediately. You must update any applications or scripts using the old key with the new value to restore connectivity. + +[VIDEO: regenerate_apikey.mp4] +{/* */} + +### Editing and Deleting +* **Edit:** Allows you to rename the key or change its expiration settings without changing the key string itself. +* **Delete:** Permanently revokes the key. Applications using this key will no longer be able to connect. + +[VIDEO: delete_apikey.mp4] +{/* */} + +--- + +## Using API Keys + +Once generated, the API Key is typically used in the connection string of your SQLite Cloud client or SDK. + +The standard format for a connection string using an API Key is: +``` +sqlitecloud://:?apikey= +``` + +When using the REST API directly, the key should be passed in the Authorization header: -The resulting table will display all the API keys associated with each user, along with their name. -![Dashboard List APIKEY](@docs-website-assets/introduction/dashboard_list_apikey.png) +```http +Authorization: Bearer +``` \ No newline at end of file diff --git a/sqlite-cloud/platform/offsync.mdx b/sqlite-cloud/platform/offsync.mdx index 5b64c90..7ec118b 100644 --- a/sqlite-cloud/platform/offsync.mdx +++ b/sqlite-cloud/platform/offsync.mdx @@ -7,9 +7,6 @@ slug: offsync --- import VideoPlayer from '@commons-components/Video/VideoPlayer.astro'; -import enableSync from '@docs-website-assets/introduction/video/dashboard_sqlite_sync_enabling.mp4'; -import connectionUrlSync from '@docs-website-assets/introduction/video/dashboard_sync_connection_url.mp4'; -import devicesSync from '@docs-website-assets/introduction/video/dashboard_sync_devices.mp4'; import Callout from "@commons-components/Information/Callout.astro"; @@ -31,35 +28,65 @@ OffSync extends standard SQLite tables with built-in support for offline work an When combined with [Row-Level Security (RLS)](/docs/rls), OffSync allows you to build secure, multi-tenant applications where each user's data is safely isolated, both on the edge and in the cloud. ---- +--- ## Configuring OffSync -You can enable and manage OffSync for your databases directly from the SQLite Cloud dashboard. -Below are the main steps: +You can enable and manage OffSync for your databases directly from the SQLite Cloud dashboard. +The OffSync panel has four tabs: **Sync Tables**, **Configuration**, **Devices**, and **Metrics**. + +### Enabling and Disabling OffSync + +When OffSync is not yet active for a database, the panel shows a brief explanation and an **Enable OffSync** button. Clicking it opens a confirmation dialog; after confirming, the database is registered with the sync service and the tabbed view appears. + +To disable OffSync, click the **Disable OffSync** button in the top-right corner of the panel and confirm the action in the dialog that appears. + +{/* */} ### Enable Tables for Synchronization -From the **Sync Tables** tab, select which tables in your database you want to keep synchronized. + +From the **Sync Tables** tab, select which tables in your database you want to keep synchronized. Once enabled, all changes to those tables will automatically sync with connected devices. - +{/* VIDEO: dashboard_offsync_sync_tables.mp4 + Show: Sync Tables tab open → toggle one or more tables on → confirmation that sync is active for those tables. */} + +### Configuration Tab +The **Configuration** tab contains two sub-sections: -### Get the Connection String -In the **Configuration** tab, copy the connection string. -Use this in your application to initialize OffSync and connect your local SQLite database with SQLite Cloud. +**Database ID** — A read-only field showing the unique identifier for your OffSync-enabled database, with a copy button for convenience. Use this ID in your application to initialize the sync connection (see the sqlite-sync README for more details): - +```sql +SELECT cloudsync_network_init(''); +``` +**Push Notifications** — Push notifications work out of the box. If you have enabled Expo enhanced security, provide your access token here. This is only required when using the `sqlite-sync-react-native` library with push mode enabled — the token adds an extra layer of security to prevent unauthorized push notifications. + +{/* VIDEO: dashboard_offsync_configuration.mp4 + Show: Configuration tab open → Database ID field with copy button clicked → scroll down to Push Notifications section → paste an Expo token → save → status changes to "Working". */} ### Manage Connected Devices -In the **Devices** tab, you can view all devices currently connected to your database. + +In the **Devices** tab, you can view all devices currently connected to your database. Here you can check their sync status and remove devices if needed. - +{/* VIDEO: dashboard_offsync_devices.mp4 + Show: Devices tab open with a list of connected devices → inspect sync status of one device → remove a device from the list. */} For OffSync to work correctly, the list of tables configured for synchronization—and their corresponding schemas—must be identical in both your local SQLite database and your SQLite Cloud database. +### Metrics Tab + +The **Metrics** tab provides visibility into daily and cumulative usage for your OffSync-enabled database: + +- **Active devices** — number of devices that have synced within the period +- **Upload bytes** — data sent from devices to SQLite Cloud +- **Download bytes** — data sent from SQLite Cloud to devices + +{/* VIDEO: dashboard_offsync_metrics.mp4 + Show: Metrics tab open → scroll through active devices chart → upload bytes chart → download bytes chart, ideally with some non-zero data visible. */} + Once enabled, any changes made to the selected tables via the SQLite Sync extension will be automatically synchronized with your SQLite Cloud database. diff --git a/sqlite-cloud/platform/pub-sub.mdx b/sqlite-cloud/platform/pub-sub.mdx index 73ebad9..d25a94b 100644 --- a/sqlite-cloud/platform/pub-sub.mdx +++ b/sqlite-cloud/platform/pub-sub.mdx @@ -6,7 +6,6 @@ status: publish slug: pub-sub --- -# SQLiteCloud Pub/Sub System **Publish/Subscribe (Pub/Sub)** is a messaging pattern that enables asynchronous communication between multiple applications. In the context of **SQLiteCloud**, Pub/Sub provides a robust way to deliver real-time updates or custom messages to subscribed clients when data changes or explicit notifications are issued. diff --git a/sqlite-cloud/platform/rls.mdx b/sqlite-cloud/platform/rls.mdx index 07bc7f4..ff40af5 100644 --- a/sqlite-cloud/platform/rls.mdx +++ b/sqlite-cloud/platform/rls.mdx @@ -254,24 +254,3 @@ OLD.status <> 'paid' **Explanation:** This policy uses the `OLD` reference to check the value of the `status` column *before* the update is applied. If the status is already `'paid'`, the condition `OLD.status <> 'paid'` will be false, and the `UPDATE` operation will be denied. This effectively makes paid invoices read-only. - - ---- - -## Advanced: RLS and SQLite Sync - -When using RLS in conjunction with SQLite Sync, it's important to understand how they interact. The Sync protocol applies changes on a column-by-column basis, which can affect how `INSERT` and `UPDATE` policies are evaluated. - -To accommodate this, SQLite Cloud offers two modes for handling RLS during sync operations, configurable via the `rls_mode` server setting using the SQLite Cloud builtin command `SET KEY rls_mode TO `. - -#### Default Mode (`rls_mode = 1`) - -To simplify policy creation for the most common use cases, the default mode does **not** enforce `INSERT` and `UPDATE` policies while applying changes from SQLite Sync. - -Instead, after the sync operation is complete, the `SELECT` policy is used to validate the final state of the row. If the user does not have permission to view the resulting row, the entire transaction is rolled back. This ensures that users cannot introduce changes that they are not allowed to see. - -#### Manual Policy Mode (`rls_mode = 0`) - -For more complex scenarios, such as implementing separate read/write permissions or restricting write access to specific columns, you can set `rls_mode` to `0`. - -In this mode, your `INSERT` and `UPDATE` policies are enforced for every incremental change applied by SQLite Sync. Because of Sync's column-by-column operation, your policies must be written to permit intermediate states. This means the policies must allow `NEW` values for non-primary key columns to be temporarily set to their default values during the sync process. diff --git a/sqlite-cloud/platform/roles.mdx b/sqlite-cloud/platform/roles.mdx new file mode 100644 index 0000000..2f525da --- /dev/null +++ b/sqlite-cloud/platform/roles.mdx @@ -0,0 +1,149 @@ +--- +title: Roles & Privileges +description: Understand the role-based access control system, built-in roles, and how to define custom access policies. +category: platform +status: publish +slug: roles +--- +import VideoPlayer from '@commons-components/Video/VideoPlayer.astro'; +import createRole from '@docs-website-assets/introduction/video/roles-privileges/roles_create_custom_role.mp4'; +import manageRole from '@docs-website-assets/introduction/video/roles-privileges/roles_manage_roles.mp4'; + +import Callout from "@commons-components/Information/Callout.astro"; + + + +In SQLite Cloud, a **Role** is a named collection of permissions (privileges) that allows specific actions on resources like databases, tables. Users can have multiple roles, which determine their access to the system. + +Roles are the bridge between Users and Resources: +* **Users** authenticate into the system. +* **Roles** define what those users are allowed to do. +* **Resources** (Databases, Tables) are the objects being accessed. + +You can manage role definitions via the SQLite Cloud Dashboard under the **Roles** section. + +--- + +## Built-in Roles + +SQLite Cloud comes with a set of pre-defined roles designed to cover the most common use cases. These roles are available immediately and cannot be modified, but they can be scoped to specific databases or tables when assigned to a user. + +### General Access Roles +* **ADMIN:** This role possesses the highest level of privileges, with unrestricted access to all assigned permissions. +* **READ:** Grants read-only access to a specified database or table. +* **READWRITE:** Offers both read and write functionality for a specified database or table. +* **DBADMIN:** Allows for administrative tasks like indexing and statistics gathering but doesn't manage users or roles. + +### Any Database Roles +These roles implicitly apply to the entire cluster (`*`) and do not require specific scoping during assignment. +* **READANYDATABASE:** Provides read-only access to any database and table. +* **READWRITEANYDATABASE:** Grants read and write capabilities across any database and table. +* **DBADMINANYDATABASE:** Provides administrative functions for any database. + +### Pub/Sub Roles +* **SUB:** Grants the subscribe privilege to a specified database, table, or channel. +* **PUB:** Offers the publish privilege to a specified database, table, or channel. +* **PUBSUB:** Combines subscribe and publish privileges for a specified database, table, or channel. +* **PUBSUBADMIN:** Allows the creation and removal of channel privileges for a specified database or channel. +* **SUBANYCHANNEL**: Provides the subscribe privilege for any channel or table. +* **PUBANYCHANNEL**: Grants the publish privilege for any channel or table. +* **PUBSUBANYCHANNEL**: Combines subscribe and publish privileges for any channel or table. +* **PUBSUBADMINANYCHANNEL**: Permits the creation and removal of channel privileges for any channel. + +### Cluster Management Roles +* **USERADMIN:** Enables the creation and modification of roles and users. +* **CLUSTERADMIN:** Empowers users to manage and monitor the cluster. +* **CLUSTERMONITOR:** Offers read-only access to cluster monitoring commands. +* **HOSTADMIN:** Allows monitoring and management of individual nodes. + + +To further refine the scope of a role or privilege, you can specify a database and table name during the [CREATE ROLE](/docs/role-commands), [GRANT ROLE](/docs/role-commands), GRANT PRIVILEGE and SET PRIVILEGE commands, as well as during the CREATE USER command. If `NULL` is used, it means that the role or privilege is not assigned and cannot function without specifying a database and table name combination. To extend the validity to any database and table, you can utilize the special `*` character. + + +Below is the technical definition of all built-in roles and their mapped privileges: + +```bash +>> LIST ROLES +-----------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------|--------------|-----------| + rolename | builtin | privileges | databasename | tablename | +-----------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------|--------------|-----------| + ADMIN | 1 | READ,INSERT,UPDATE,DELETE,READWRITE,PRAGMA,CREATE_TABLE,CREATE_INDEX,CREATE_VIEW, | | | + | | CREATE_TRIGGER,DROP_TABLE,DROP_INDEX,DROP_VIEW,DROP_TRIGGER,ALTER_TABLE,ANALYZE, | | | + | | ATTACH,DETACH,DBADMIN,SUB,PUB,PUBSUB,BACKUP,RESTORE,DOWNLOAD,PLUGIN,SETTINGS,USERADMIN, | | | + | | CLUSTERADMIN,CLUSTERMONITOR,CREATE_DATABASE,DROP_DATABASE,HOSTADMIN,SWITCH_USER,PUBSUBCREATE,PUBSUBADMIN,WEBLITE,ADMIN | NULL | NULL | + READ | 1 | READ | NULL | NULL | + READANYDATABASE | 1 | READ | * | * | + READWRITE | 1 | READ,INSERT,UPDATE,DELETE,READWRITE | NULL | NULL | + READWRITEANYDATABASE | 1 | READ,INSERT,UPDATE,DELETE,READWRITE | * | * | + DBADMIN | 1 | READ,INSERT,UPDATE,DELETE,READWRITE,PRAGMA,CREATE_TABLE,CREATE_INDEX,CREATE_VIEW, | | | + | | CREATE_TRIGGER,DROP_TABLE,DROP_INDEX,DROP_VIEW,DROP_TRIGGER,ALTER_TABLE,ANALYZE,ATTACH,DETACH,DBADMIN | NULL | NULL | + DBADMINANYDATABASE | 1 | READ,INSERT,UPDATE,DELETE,READWRITE,PRAGMA,CREATE_TABLE,CREATE_INDEX,CREATE_VIEW, | | | + | | CREATE_TRIGGER,DROP_TABLE,DROP_INDEX,DROP_VIEW,DROP_TRIGGER,ALTER_TABLE,ANALYZE,ATTACH,DETACH,DBADMIN | * | * | + USERADMIN | 1 | USERADMIN | * | * | + CLUSTERADMIN | 1 | CLUSTERADMIN | * | * | + CLUSTERMONITOR | 1 | CLUSTERMONITOR | * | * | + HOSTADMIN | 1 | BACKUP,RESTORE,DOWNLOAD,CREATE_DATABASE,DROP_DATABASE,HOSTADMIN | * | * | + SUB | 1 | SUB | NULL | NULL | + SUBANYCHANNEL | 1 | SUB | * | * | + PUB | 1 | PUB | NULL | NULL | + PUBANYCHANNEL | 1 | PUB | * | * | + PUBSUB | 1 | SUB,PUB,PUBSUB | NULL | NULL | + PUBSUBANYCHANNEL | 1 | SUB,PUB,PUBSUB | * | * | + PUBSUBADMIN | 1 | SUB,PUB,PUBSUB,PUBSUBCREATE,PUBSUBADMIN | NULL | NULL | + PUBSUBADMINANYCHANNEL | 1 | SUB,PUB,PUBSUB,PUBSUBCREATE,PUBSUBADMIN | * | * | +-----------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------|--------------|-----------| +``` + +--- + +## Custom Roles + +If the built-in roles do not fit your specific security model, you can create **User-Defined Roles**. This allows you to mix and match specific privileges. + +### Creating a Custom Role + +1. Navigate to the **Roles** section in the left sidebar. +2. Click the **Create Role** button. +3. **Name:** Enter a unique name for the role (e.g., `AuditLogger`, `HRManager`). +4. **Privileges:** Select the specific atomic privileges this role should possess (see list below). +5. Click **Create**. + + + +### Managing Roles + +From the Roles list, you can: +* **Inspect:** Click on a role to see exactly which privileges it contains. +* **Edit:** Add or remove privileges from a custom role (Built-in roles cannot be edited). +* **Delete:** Remove a custom role. + + + +--- + +## Privileges Reference + +In a role-based access control system, a **Privilege** represents a specific action or permission that a user or role is allowed to perform within the system. +It defines what a user can or cannot do, such as reading, writing, or managing certain resources like tables, databases, or settings. +Essentially, a privilege is a **right** or **ability** granted to a user or role, specifying their level of access and control over the system's resources. + +A privilege can be granted, revoked and assigned to a given role. +A role can contains any combination of privileges. + +Below is the complete list of available privileges: + +| | | | +| :--- | :--- | :--- | +| NONE | READ | INSERT | +| UPDATE | DELETE | READWRITE | +| PRAGMA | CREATE_TABLE | CREATE_INDEX | +| CREATE_VIEW | CREATE_TRIGGER | DROP_TABLE | +| DROP_INDEX | DROP_VIEW | DROP_TRIGGER | +| ALTER_TABLE | ANALYZE | ATTACH | +| DETACH | DBADMIN | SUB | +| PUB | PUBSUB | BACKUP | +| RESTORE | DOWNLOAD | PLUGIN | +| SETTINGS | USERADMIN | CLUSTERADMIN | +| CLUSTERMONITOR | CREATE_DATABASE | DROP_DATABASE | +| HOSTADMIN | SWITCH_USER | PUBSUBCREATE | +| PUBSUBADMIN | WEBLITE | ADMIN | \ No newline at end of file diff --git a/sqlite-cloud/platform/security.mdx b/sqlite-cloud/platform/security.mdx index 961c842..327821e 100644 --- a/sqlite-cloud/platform/security.mdx +++ b/sqlite-cloud/platform/security.mdx @@ -38,24 +38,9 @@ SQLite Cloud offers a comprehensive system of built-in roles designed to provide Here is an overview of the built-in roles: -- **ADMIN**: This role possesses the highest level of privileges, with unrestricted access to all assigned permissions. -- **READ**: Grants read-only access to a specified database or table. -- **READANYDATABASE**: Provides read-only access to any database and table. -- **READWRITE**: Offers both read and write functionality for a specified database or table. -- **READWRITEANYDATABASE**: Grants read and write capabilities across any database and table. -- **DBADMIN**: Allows for administrative tasks like indexing and statistics gathering but doesn't manage users or roles. -- **DBADMINANYDATABASE**: Provides administrative functions for any database. -- **USERADMIN**: Enables the creation and modification of roles and users. -- **CLUSTERADMIN**: Empowers users to manage and monitor the cluster. -- **CLUSTERMONITOR**: Offers read-only access to cluster monitoring commands. -- **HOSTADMIN**: Allows monitoring and management of individual nodes. -- **SUB**: Grants the subscribe privilege to a specified database, table, or channel. - **SUBANYCHANNEL**: Provides the subscribe privilege for any channel or table. -- **PUB**: Offers the publish privilege to a specified database, table, or channel. - **PUBANYCHANNEL**: Grants the publish privilege for any channel or table. -- **PUBSUB**: Combines subscribe and publish privileges for a specified database, table, or channel. - **PUBSUBANYCHANNEL**: Combines subscribe and publish privileges for any channel or table. -- **PUBSUBADMIN**: Allows the creation and removal of channel privileges for a specified database or channel. - **PUBSUBADMINANYCHANNEL**: Permits the creation and removal of channel privileges for any channel. diff --git a/sqlite-cloud/platform/users.mdx b/sqlite-cloud/platform/users.mdx new file mode 100644 index 0000000..b4a75f6 --- /dev/null +++ b/sqlite-cloud/platform/users.mdx @@ -0,0 +1,113 @@ +--- +title: Users +description: Manage users, credentials, and access scopes in SQLite Cloud. +category: platform +status: publish +slug: users +--- + +import VideoPlayer from '@commons-components/Video/VideoPlayer.astro'; +import userCreationFlow from '@docs-website-assets/introduction/video/users/dashboard_user_creation_flow.mp4'; +import userManagementActions from '@docs-website-assets/introduction/video/users/dashboard_user_management_actions.mp4'; +import userPswUpdate from '@docs-website-assets/introduction/video/users/dashboard_user_password_update.mp4'; +import userGrantingRole from '@docs-website-assets/introduction/video/users/dashboard_granting_roles_scope.mp4'; +import userRemoveRole from '@docs-website-assets/introduction/video/users/dashboard_remove_roles_scope.mp4'; +import userCreateApikey from '@docs-website-assets/introduction/video/users/dashboard_users_create_api_key.mp4'; +import userManageApikey from '@docs-website-assets/introduction/video/users/dashboard_users_manage_api_key.mp4'; + + +SQLite Cloud provides secure access to resources through role-based authorization, which ensures user isolation and enhances security and manageability. In SQLite Cloud, roles serve as the foundation blocks for user access, and the level of user access to the database system is determined by the assigned roles. Users have no access to the system outside the designated roles. + +You can manage your cluster's users via the SQLite Cloud Dashboard under the **Users** section. + +--- + +### Creating a User + +To add a new user to your cluster: + +1. Navigate to the **Users** section in the left sidebar. +2. Click the **+** button next to the search bar. +3. In the **Create User** modal, enter the **User Name**. +4. Enter a **Password** or use the **Generate** button to create a secure one automatically. +5. Confirm the password and click **Create**. + + + +### Managing User Status + +Once a user is selected from the list, you can manage their lifecycle using the controls in the top right corner or the context menu (three dots) next to their name in the list. + +* **Disable User:** Click **Disable User** to temporarily revoke access without deleting the account or its configurations. +* **Rename:** Change the username while preserving assigned roles and keys. +* **Delete:** Permanently remove the user from the cluster. + + + +--- + +## User Configuration & Password Rotation + +You can update a user's password at any time through the **Configuration** tab. + +1. Select the user from the list. +2. Click on the **Configuration** tab. +3. Enter the **New Password** and confirm it in the **Confirm Password** field. +4. Click **Update Password**. + + + +--- + +## Assigning Roles + +The **Roles** tab allows you to control what a user can do. A user can have multiple roles, and the combination of these roles determines their effective permissions. + +### Granting a Role + +The Grant Roles interface allows you to assign roles with precise scoping (limiting a role to specific databases or tables) directly from the assignment screen. + +1. Select the user and ensure you are on the **Roles** tab. +2. Click the **Grant Roles** button. +3. **Select Scope (Optional):** By default, roles apply to all databases (`*`) and all tables (`*`). You can restrict the role by selecting a specific **Database** and **Table** from the dropdowns at the top. +4. **Select Roles:** Browse the list of roles. You can filter by **Built-in** or **Custom** roles using the radio buttons, or use the search bar to find a specific role. +5. Check the box next to the role(s) you wish to assign. +6. Click **Grant**. + + + +### Revoking a Role + +To remove a role from a user: +1. In the **Roles** tab, find the role in the list. +2. Click the context menu (three dots) on the right side of the role row. +3. Select **Delete**. + + + + +--- + +## User API Keys + +Authentication is primarily handled via **API Keys**. You can generate multiple keys specific to a user, which inherit that user's permissions. These keys inherit the user's permissions and are ideal for programmatic access, SDKs, and REST API usage + +### Creating an API Key + +1. Select the user and switch to the **API Keys** tab. +2. Click **Create API Key**. +3. **Name:** Give the key a descriptive name (e.g., "Production App", "Testing Script"). +4. **Expiration:** Choose whether the key **Never expires** or **Set expiration date** to have it automatically invalidate after a specific time. +5. Click **Create**. + + + +### Managing API Keys + +Existing keys are listed in the API Keys tab. From here you can: + +* **View Details:** See the key name, masked value, creation date, and expiration status. +* **Regenerate:** If a key is compromised, use the context menu to **Regenerate** it. This invalidates the old key string and provides a new one immediately. +* **Delete:** Permanently remove an API Key to revoke access for any application using it. + +