Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,6 +10,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- [EE] Added multi-owner support with promote/demote actions. [#988](https://github.com/sourcebot-dev/sourcebot/pull/988)
- [EE] Added `PERMISSION_SYNC_REPO_DRIVEN_ENABLED` environment variable to enable/disable repo-driven permission syncing. [#989](https://github.com/sourcebot-dev/sourcebot/pull/989)
- [EE] Added `enforcePermissions` per-connection flag to control whether repository permissions are enforced for a given connection. Defaults to the value of `PERMISSION_SYNC_ENABLED`. [#991](https://github.com/sourcebot-dev/sourcebot/pull/991)
- [EE] Added `repoDrivenPermissionSyncIntervalMs` and `userDrivenPermissionSyncIntervalMs` config settings, deprecating the `experiment_` prefixed variants (still respected as fallbacks). [#991](https://github.com/sourcebot-dev/sourcebot/pull/991)

### Changed
- [EE] Promoted `PERMISSION_SYNC_ENABLED` as the canonical env var for enabling permission syncing, deprecating `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` (still respected as a fallback). [#991](https://github.com/sourcebot-dev/sourcebot/pull/991)

## [4.15.3] - 2026-03-10

Expand Down
6 changes: 4 additions & 2 deletions docs/docs/configuration/config-file.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -50,8 +50,10 @@ The following are settings that can be provided in your config file to modify So
| `repoGarbageCollectionGracePeriodMs` | number | 10 seconds | 1 | Grace period to avoid deleting shards while loading. |
| `repoIndexTimeoutMs` | number | 2 hours | 1 | Timeout for a single repo‑indexing run. |
| `enablePublicAccess` **(deprecated)** | boolean | false | — | Use the `FORCE_ENABLE_ANONYMOUS_ACCESS` environment variable instead. |
| `experiment_repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the repo permission syncer should run. |
| `experiment_userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the user permission syncer should run. |
| `repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the repo permission syncer should run. |
| `userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the user permission syncer should run. |
| `experiment_repoDrivenPermissionSyncIntervalMs` **(deprecated)** | number | 24 hours | 1 | Use `repoDrivenPermissionSyncIntervalMs` instead. |
| `experiment_userDrivenPermissionSyncIntervalMs` **(deprecated)** | number | 24 hours | 1 | Use `userDrivenPermissionSyncIntervalMs` instead. |
Comment thread
brendan-kellam marked this conversation as resolved.
| `maxAccountPermissionSyncJobConcurrency` | number | 8 | 1 | Concurrent account permission sync jobs. |
| `maxRepoPermissionSyncJobConcurrency` | number | 8 | 1 | Concurrent repo permission sync jobs. |

Expand Down
5 changes: 3 additions & 2 deletions docs/docs/configuration/environment-variables.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -45,8 +45,9 @@ The following environment variables allow you to configure your Sourcebot deploy
| `SOURCEBOT_EE_AUDIT_RETENTION_DAYS` | `180` | <p>The number of days to retain audit logs. Audit log records older than this will be automatically pruned daily. Set to `0` to disable pruning and retain logs indefinitely.</p> |
| `AUTH_EE_GCP_IAP_ENABLED` | `false` | <p>When enabled, allows Sourcebot to automatically register/login from a successful GCP IAP redirect</p> |
| `AUTH_EE_GCP_IAP_AUDIENCE` | - | <p>The GCP IAP audience to use when verifying JWT tokens. Must be set to enable GCP IAP JIT provisioning</p> |
| `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` | `false` | <p>Enables [permission syncing](/docs/features/permission-syncing).</p> |
| `PERMISSION_SYNC_REPO_DRIVEN_ENABLED` | `true` | <p>Enables/disables [repo-driven permission syncing](/docs/features/permission-syncing#how-it-works). Only applies when `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` is `true`.</p> |
| `PERMISSION_SYNC_ENABLED` | `false` | <p>Enables [permission syncing](/docs/features/permission-syncing).</p> |
| `PERMISSION_SYNC_REPO_DRIVEN_ENABLED` | `true` | <p>Enables/disables [repo-driven permission syncing](/docs/features/permission-syncing#how-it-works). Only applies when `PERMISSION_SYNC_ENABLED` is `true`.</p> |
Comment thread
brendan-kellam marked this conversation as resolved.
| `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` **(deprecated)** | `false` | <p>Deprecated. Use `PERMISSION_SYNC_ENABLED` instead.</p> |
| `AUTH_EE_ALLOW_EMAIL_ACCOUNT_LINKING` | `true` | <p>When enabled, different SSO accounts with the same email address will automatically be linked.</p> |


Expand Down
78 changes: 56 additions & 22 deletions docs/docs/features/permission-syncing.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,11 +18,11 @@ that they have access to on the code host. Practically, this means:
- Ask Sourcebot (and the underlying LLM) will only have access to repositories that the user has access to.
- File browsing is scoped to the repositories that the user has access to.

Permission syncing can be enabled by setting the `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` environment variable to `true`.
Permission syncing can be enabled by setting the `PERMISSION_SYNC_ENABLED` environment variable to `true`.

```bash
docker run \
-e EXPERIMENT_EE_PERMISSION_SYNC_ENABLED=true \
-e PERMISSION_SYNC_ENABLED=true \
/* additional args */ \
ghcr.io/sourcebot-dev/sourcebot:latest
```
Expand DownExpand Up@@ -97,9 +97,9 @@ Permission syncing works with **Bitbucket Cloud**. OAuth tokens must assume the
- Membership in the [project that contains the repository](https://support.atlassian.com/bitbucket-cloud/docs/configure-project-permissions-for-users-and-groups/)
- Membership in a group that is part of a project containing the repository

These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all private repositories accessible to each authenticated user. However, there may be a delay between when a repository is added and when affected users gain access in Sourcebot (up to the `experiment_userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).
These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all private repositories accessible to each authenticated user. However, there may be a delay between when a repository is added and when affected users gain access in Sourcebot (up to the `userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).

If your workspace relies heavily on group or project-level permissions rather than direct user grants, we recommend reducing the `experiment_userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
If your workspace relies heavily on group or project-level permissions rather than direct user grants, we recommend reducing the `userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
</Warning>

**Notes:**
Expand All@@ -120,16 +120,64 @@ Permission syncing works with **Bitbucket Data Center**. OAuth tokens must assum
- Project-level permissions (inherited by all repos in the project)
- Group membership

These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all repositories accessible to each authenticated user using the `REPO_READ` scope. However, there may be a delay between when access is granted and when affected users see the repository in Sourcebot (up to the `experiment_userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).
These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all repositories accessible to each authenticated user using the `REPO_READ` scope. However, there may be a delay between when access is granted and when affected users see the repository in Sourcebot (up to the `userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).

If your instance relies heavily on project or group-level permissions, we recommend reducing the `experiment_userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
If your instance relies heavily on project or group-level permissions, we recommend reducing the `userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
</Warning>

**Notes:**
- A Bitbucket Data Center [external identity provider](/docs/configuration/idp#bitbucket-server) must be configured to (1) correlate a Sourcebot user with a Bitbucket Data Center user, and (2) to list repositories that the user has access to for [User driven syncing](/docs/features/permission-syncing#how-it-works).
- The connection token must have **Repository Read** permissions so Sourcebot can read repository-level user permissions for [Repo driven syncing](/docs/features/permission-syncing#how-it-works).
- OAuth tokens require the `REPO_READ` scope to list accessible repositories during [User driven syncing](/docs/features/permission-syncing#how-it-works).

# Manually refreshing permissions

If a user's permissions have changed and they need access updated immediately (without waiting for the next scheduled sync), they can trigger a manual refresh from the **Linked Accounts** page:

1. Navigate to **Settings → Linked Accounts**.
2. Click the **Connected** button next to the relevant code host account.
3. Select **Refresh Permissions** from the dropdown.

<Frame>
<img src="/images/linked_accounts_refresh_permissions.png" alt="Linked Accounts - Refresh Permissions" />
</Frame>

The button will show a spinner while the sync is in progress and display a confirmation once it completes.


# Overriding enforcement per connection

Each [connection](/docs/connections/overview) supports an `enforcePermissions` flag that controls whether permissions are enforced for repositories in that connection. This lets you mix code hosts in a single deployment - for example, enforcing access control on a private GitHub connection while keeping an internal Gerrit instance open to all users.

By default, `enforcePermissions` inherits the value of `PERMISSION_SYNC_ENABLED`. You can override it per connection in the [config file](/docs/configuration/config-file):

```json
{
"connections": {
"my-github": {
"type": "github",
"enforcePermissions": true
},
"my-gerrit": {
"type": "gerrit",
"url": "https://gerrit.example.com",
"enforcePermissions": false
}
}
}
```

Setting `enforcePermissions: false` on a connection makes all repositories from that connection accessible to any user, regardless of the global `PERMISSION_SYNC_ENABLED` setting.

The table below shows when permissions are enforced based on the combination of `PERMISSION_SYNC_ENABLED` and `enforcePermissions`:

| `PERMISSION_SYNC_ENABLED` | `enforcePermissions` | Permissions enforced? |
|--------------------------|---------------------|-----------------------|
| `true` | `true` | Yes |
| `true` | `false` | No |
| `false` | `true` | No |
| `false` | `false` | No |
Comment thread
brendan-kellam marked this conversation as resolved.

# How it works

Permission syncing works by periodically syncing ACLs from the code host(s) to Sourcebot to build an internal mapping between Users and Repositories. This mapping is hydrated in two directions:
Expand All@@ -146,19 +194,5 @@ The sync intervals can be configured using the following settings in the [config

| Setting | Type | Default | Minimum |
|-------------------------------------------------|---------|------------|---------|
| `experiment_repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |
| `experiment_userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |

## Manually refreshing permissions

If a user's permissions have changed and they need access updated immediately (without waiting for the next scheduled sync), they can trigger a manual refresh from the **Linked Accounts** page:

1. Navigate to **Settings → Linked Accounts**.
2. Click the **Connected** button next to the relevant code host account.
3. Select **Refresh Permissions** from the dropdown.

<Frame>
<img src="/images/linked_accounts_refresh_permissions.png" alt="Linked Accounts - Refresh Permissions" />
</Frame>

The button will show a spinner while the sync is in progress and display a confirmation once it completes.
| `repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |
| `userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/azuredevops.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -189,6 +189,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/bitbucket.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -162,6 +162,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
28 changes: 28 additions & 0 deletions docs/snippets/schemas/v3/connection.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -205,6 +205,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -407,6 +411,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -562,6 +570,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -669,6 +681,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -839,6 +855,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -1047,6 +1067,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -1116,6 +1140,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/genericGitHost.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -60,6 +60,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/gerrit.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -100,6 +100,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/gitea.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -148,6 +148,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/github.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -201,6 +201,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/gitlab.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -195,6 +195,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,6 +10,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- [EE] Added multi-owner support with promote/demote actions. [#988](https://github.com/sourcebot-dev/sourcebot/pull/988)
- [EE] Added `PERMISSION_SYNC_REPO_DRIVEN_ENABLED` environment variable to enable/disable repo-driven permission syncing. [#989](https://github.com/sourcebot-dev/sourcebot/pull/989)
- [EE] Added `enforcePermissions` per-connection flag to control whether repository permissions are enforced for a given connection. Defaults to the value of `PERMISSION_SYNC_ENABLED`. [#991](https://github.com/sourcebot-dev/sourcebot/pull/991)
- [EE] Added `repoDrivenPermissionSyncIntervalMs` and `userDrivenPermissionSyncIntervalMs` config settings, deprecating the `experiment_` prefixed variants (still respected as fallbacks). [#991](https://github.com/sourcebot-dev/sourcebot/pull/991)

### Changed
- [EE] Promoted `PERMISSION_SYNC_ENABLED` as the canonical env var for enabling permission syncing, deprecating `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` (still respected as a fallback). [#991](https://github.com/sourcebot-dev/sourcebot/pull/991)

## [4.15.3] - 2026-03-10

Expand Down
6 changes: 4 additions & 2 deletions docs/docs/configuration/config-file.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -50,8 +50,10 @@ The following are settings that can be provided in your config file to modify So
| `repoGarbageCollectionGracePeriodMs` | number | 10 seconds | 1 | Grace period to avoid deleting shards while loading. |
| `repoIndexTimeoutMs` | number | 2 hours | 1 | Timeout for a single repo‑indexing run. |
| `enablePublicAccess` **(deprecated)** | boolean | false | — | Use the `FORCE_ENABLE_ANONYMOUS_ACCESS` environment variable instead. |
| `experiment_repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the repo permission syncer should run. |
| `experiment_userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the user permission syncer should run. |
| `repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the repo permission syncer should run. |
| `userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the user permission syncer should run. |
| `experiment_repoDrivenPermissionSyncIntervalMs` **(deprecated)** | number | 24 hours | 1 | Use `repoDrivenPermissionSyncIntervalMs` instead. |
| `experiment_userDrivenPermissionSyncIntervalMs` **(deprecated)** | number | 24 hours | 1 | Use `userDrivenPermissionSyncIntervalMs` instead. |
Comment thread
brendan-kellam marked this conversation as resolved.
| `maxAccountPermissionSyncJobConcurrency` | number | 8 | 1 | Concurrent account permission sync jobs. |
| `maxRepoPermissionSyncJobConcurrency` | number | 8 | 1 | Concurrent repo permission sync jobs. |

Expand Down
5 changes: 3 additions & 2 deletions docs/docs/configuration/environment-variables.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -45,8 +45,9 @@ The following environment variables allow you to configure your Sourcebot deploy
| `SOURCEBOT_EE_AUDIT_RETENTION_DAYS` | `180` | <p>The number of days to retain audit logs. Audit log records older than this will be automatically pruned daily. Set to `0` to disable pruning and retain logs indefinitely.</p> |
| `AUTH_EE_GCP_IAP_ENABLED` | `false` | <p>When enabled, allows Sourcebot to automatically register/login from a successful GCP IAP redirect</p> |
| `AUTH_EE_GCP_IAP_AUDIENCE` | - | <p>The GCP IAP audience to use when verifying JWT tokens. Must be set to enable GCP IAP JIT provisioning</p> |
| `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` | `false` | <p>Enables [permission syncing](/docs/features/permission-syncing).</p> |
| `PERMISSION_SYNC_REPO_DRIVEN_ENABLED` | `true` | <p>Enables/disables [repo-driven permission syncing](/docs/features/permission-syncing#how-it-works). Only applies when `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` is `true`.</p> |
| `PERMISSION_SYNC_ENABLED` | `false` | <p>Enables [permission syncing](/docs/features/permission-syncing).</p> |
| `PERMISSION_SYNC_REPO_DRIVEN_ENABLED` | `true` | <p>Enables/disables [repo-driven permission syncing](/docs/features/permission-syncing#how-it-works). Only applies when `PERMISSION_SYNC_ENABLED` is `true`.</p> |
Comment thread
brendan-kellam marked this conversation as resolved.
| `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` **(deprecated)** | `false` | <p>Deprecated. Use `PERMISSION_SYNC_ENABLED` instead.</p> |
| `AUTH_EE_ALLOW_EMAIL_ACCOUNT_LINKING` | `true` | <p>When enabled, different SSO accounts with the same email address will automatically be linked.</p> |


Expand Down
78 changes: 56 additions & 22 deletions docs/docs/features/permission-syncing.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,11 +18,11 @@ that they have access to on the code host. Practically, this means:
- Ask Sourcebot (and the underlying LLM) will only have access to repositories that the user has access to.
- File browsing is scoped to the repositories that the user has access to.

Permission syncing can be enabled by setting the `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` environment variable to `true`.
Permission syncing can be enabled by setting the `PERMISSION_SYNC_ENABLED` environment variable to `true`.

```bash
docker run \
-e EXPERIMENT_EE_PERMISSION_SYNC_ENABLED=true \
-e PERMISSION_SYNC_ENABLED=true \
/* additional args */ \
ghcr.io/sourcebot-dev/sourcebot:latest
```
Expand DownExpand Up@@ -97,9 +97,9 @@ Permission syncing works with **Bitbucket Cloud**. OAuth tokens must assume the
- Membership in the [project that contains the repository](https://support.atlassian.com/bitbucket-cloud/docs/configure-project-permissions-for-users-and-groups/)
- Membership in a group that is part of a project containing the repository

These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all private repositories accessible to each authenticated user. However, there may be a delay between when a repository is added and when affected users gain access in Sourcebot (up to the `experiment_userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).
These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all private repositories accessible to each authenticated user. However, there may be a delay between when a repository is added and when affected users gain access in Sourcebot (up to the `userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).

If your workspace relies heavily on group or project-level permissions rather than direct user grants, we recommend reducing the `experiment_userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
If your workspace relies heavily on group or project-level permissions rather than direct user grants, we recommend reducing the `userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
</Warning>

**Notes:**
Expand All@@ -120,16 +120,64 @@ Permission syncing works with **Bitbucket Data Center**. OAuth tokens must assum
- Project-level permissions (inherited by all repos in the project)
- Group membership

These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all repositories accessible to each authenticated user using the `REPO_READ` scope. However, there may be a delay between when access is granted and when affected users see the repository in Sourcebot (up to the `experiment_userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).
These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all repositories accessible to each authenticated user using the `REPO_READ` scope. However, there may be a delay between when access is granted and when affected users see the repository in Sourcebot (up to the `userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).

If your instance relies heavily on project or group-level permissions, we recommend reducing the `experiment_userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
If your instance relies heavily on project or group-level permissions, we recommend reducing the `userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
</Warning>

**Notes:**
- A Bitbucket Data Center [external identity provider](/docs/configuration/idp#bitbucket-server) must be configured to (1) correlate a Sourcebot user with a Bitbucket Data Center user, and (2) to list repositories that the user has access to for [User driven syncing](/docs/features/permission-syncing#how-it-works).
- The connection token must have **Repository Read** permissions so Sourcebot can read repository-level user permissions for [Repo driven syncing](/docs/features/permission-syncing#how-it-works).
- OAuth tokens require the `REPO_READ` scope to list accessible repositories during [User driven syncing](/docs/features/permission-syncing#how-it-works).

# Manually refreshing permissions

If a user's permissions have changed and they need access updated immediately (without waiting for the next scheduled sync), they can trigger a manual refresh from the **Linked Accounts** page:

1. Navigate to **Settings → Linked Accounts**.
2. Click the **Connected** button next to the relevant code host account.
3. Select **Refresh Permissions** from the dropdown.

<Frame>
<img src="/images/linked_accounts_refresh_permissions.png" alt="Linked Accounts - Refresh Permissions" />
</Frame>

The button will show a spinner while the sync is in progress and display a confirmation once it completes.


# Overriding enforcement per connection

Each [connection](/docs/connections/overview) supports an `enforcePermissions` flag that controls whether permissions are enforced for repositories in that connection. This lets you mix code hosts in a single deployment - for example, enforcing access control on a private GitHub connection while keeping an internal Gerrit instance open to all users.

By default, `enforcePermissions` inherits the value of `PERMISSION_SYNC_ENABLED`. You can override it per connection in the [config file](/docs/configuration/config-file):

```json
{
"connections": {
"my-github": {
"type": "github",
"enforcePermissions": true
},
"my-gerrit": {
"type": "gerrit",
"url": "https://gerrit.example.com",
"enforcePermissions": false
}
}
}
```

Setting `enforcePermissions: false` on a connection makes all repositories from that connection accessible to any user, regardless of the global `PERMISSION_SYNC_ENABLED` setting.

The table below shows when permissions are enforced based on the combination of `PERMISSION_SYNC_ENABLED` and `enforcePermissions`:

| `PERMISSION_SYNC_ENABLED` | `enforcePermissions` | Permissions enforced? |
|--------------------------|---------------------|-----------------------|
| `true` | `true` | Yes |
| `true` | `false` | No |
| `false` | `true` | No |
| `false` | `false` | No |
Comment thread
brendan-kellam marked this conversation as resolved.

# How it works

Permission syncing works by periodically syncing ACLs from the code host(s) to Sourcebot to build an internal mapping between Users and Repositories. This mapping is hydrated in two directions:
Expand All@@ -146,19 +194,5 @@ The sync intervals can be configured using the following settings in the [config

| Setting | Type | Default | Minimum |
|-------------------------------------------------|---------|------------|---------|
| `experiment_repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |
| `experiment_userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |

## Manually refreshing permissions

If a user's permissions have changed and they need access updated immediately (without waiting for the next scheduled sync), they can trigger a manual refresh from the **Linked Accounts** page:

1. Navigate to **Settings → Linked Accounts**.
2. Click the **Connected** button next to the relevant code host account.
3. Select **Refresh Permissions** from the dropdown.

<Frame>
<img src="/images/linked_accounts_refresh_permissions.png" alt="Linked Accounts - Refresh Permissions" />
</Frame>

The button will show a spinner while the sync is in progress and display a confirmation once it completes.
| `repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |
| `userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/azuredevops.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -189,6 +189,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/bitbucket.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -162,6 +162,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
28 changes: 28 additions & 0 deletions docs/snippets/schemas/v3/connection.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -205,6 +205,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -407,6 +411,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -562,6 +570,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -669,6 +681,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -839,6 +855,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -1047,6 +1067,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -1116,6 +1140,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/genericGitHost.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -60,6 +60,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/gerrit.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -100,6 +100,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/gitea.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -148,6 +148,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/github.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -201,6 +201,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/gitlab.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -195,6 +195,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,6 +10,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- [EE] Added multi-owner support with promote/demote actions. [#988](https://github.com/sourcebot-dev/sourcebot/pull/988)
- [EE] Added `PERMISSION_SYNC_REPO_DRIVEN_ENABLED` environment variable to enable/disable repo-driven permission syncing. [#989](https://github.com/sourcebot-dev/sourcebot/pull/989)
- [EE] Added `enforcePermissions` per-connection flag to control whether repository permissions are enforced for a given connection. Defaults to the value of `PERMISSION_SYNC_ENABLED`. [#991](https://github.com/sourcebot-dev/sourcebot/pull/991)
- [EE] Added `repoDrivenPermissionSyncIntervalMs` and `userDrivenPermissionSyncIntervalMs` config settings, deprecating the `experiment_` prefixed variants (still respected as fallbacks). [#991](https://github.com/sourcebot-dev/sourcebot/pull/991)

### Changed
- [EE] Promoted `PERMISSION_SYNC_ENABLED` as the canonical env var for enabling permission syncing, deprecating `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` (still respected as a fallback). [#991](https://github.com/sourcebot-dev/sourcebot/pull/991)

## [4.15.3] - 2026-03-10

Expand Down
6 changes: 4 additions & 2 deletions docs/docs/configuration/config-file.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -50,8 +50,10 @@ The following are settings that can be provided in your config file to modify So
| `repoGarbageCollectionGracePeriodMs` | number | 10 seconds | 1 | Grace period to avoid deleting shards while loading. |
| `repoIndexTimeoutMs` | number | 2 hours | 1 | Timeout for a single repo‑indexing run. |
| `enablePublicAccess` **(deprecated)** | boolean | false | — | Use the `FORCE_ENABLE_ANONYMOUS_ACCESS` environment variable instead. |
| `experiment_repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the repo permission syncer should run. |
| `experiment_userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the user permission syncer should run. |
| `repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the repo permission syncer should run. |
| `userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the user permission syncer should run. |
| `experiment_repoDrivenPermissionSyncIntervalMs` **(deprecated)** | number | 24 hours | 1 | Use `repoDrivenPermissionSyncIntervalMs` instead. |
| `experiment_userDrivenPermissionSyncIntervalMs` **(deprecated)** | number | 24 hours | 1 | Use `userDrivenPermissionSyncIntervalMs` instead. |
Comment thread
brendan-kellam marked this conversation as resolved.
| `maxAccountPermissionSyncJobConcurrency` | number | 8 | 1 | Concurrent account permission sync jobs. |
| `maxRepoPermissionSyncJobConcurrency` | number | 8 | 1 | Concurrent repo permission sync jobs. |

Expand Down
5 changes: 3 additions & 2 deletions docs/docs/configuration/environment-variables.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -45,8 +45,9 @@ The following environment variables allow you to configure your Sourcebot deploy
| `SOURCEBOT_EE_AUDIT_RETENTION_DAYS` | `180` | <p>The number of days to retain audit logs. Audit log records older than this will be automatically pruned daily. Set to `0` to disable pruning and retain logs indefinitely.</p> |
| `AUTH_EE_GCP_IAP_ENABLED` | `false` | <p>When enabled, allows Sourcebot to automatically register/login from a successful GCP IAP redirect</p> |
| `AUTH_EE_GCP_IAP_AUDIENCE` | - | <p>The GCP IAP audience to use when verifying JWT tokens. Must be set to enable GCP IAP JIT provisioning</p> |
| `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` | `false` | <p>Enables [permission syncing](/docs/features/permission-syncing).</p> |
| `PERMISSION_SYNC_REPO_DRIVEN_ENABLED` | `true` | <p>Enables/disables [repo-driven permission syncing](/docs/features/permission-syncing#how-it-works). Only applies when `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` is `true`.</p> |
| `PERMISSION_SYNC_ENABLED` | `false` | <p>Enables [permission syncing](/docs/features/permission-syncing).</p> |
| `PERMISSION_SYNC_REPO_DRIVEN_ENABLED` | `true` | <p>Enables/disables [repo-driven permission syncing](/docs/features/permission-syncing#how-it-works). Only applies when `PERMISSION_SYNC_ENABLED` is `true`.</p> |
Comment thread
brendan-kellam marked this conversation as resolved.
| `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` **(deprecated)** | `false` | <p>Deprecated. Use `PERMISSION_SYNC_ENABLED` instead.</p> |
| `AUTH_EE_ALLOW_EMAIL_ACCOUNT_LINKING` | `true` | <p>When enabled, different SSO accounts with the same email address will automatically be linked.</p> |


Expand Down
78 changes: 56 additions & 22 deletions docs/docs/features/permission-syncing.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,11 +18,11 @@ that they have access to on the code host. Practically, this means:
- Ask Sourcebot (and the underlying LLM) will only have access to repositories that the user has access to.
- File browsing is scoped to the repositories that the user has access to.

Permission syncing can be enabled by setting the `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` environment variable to `true`.
Permission syncing can be enabled by setting the `PERMISSION_SYNC_ENABLED` environment variable to `true`.

```bash
docker run \
-e EXPERIMENT_EE_PERMISSION_SYNC_ENABLED=true \
-e PERMISSION_SYNC_ENABLED=true \
/* additional args */ \
ghcr.io/sourcebot-dev/sourcebot:latest
```
Expand DownExpand Up@@ -97,9 +97,9 @@ Permission syncing works with **Bitbucket Cloud**. OAuth tokens must assume the
- Membership in the [project that contains the repository](https://support.atlassian.com/bitbucket-cloud/docs/configure-project-permissions-for-users-and-groups/)
- Membership in a group that is part of a project containing the repository

These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all private repositories accessible to each authenticated user. However, there may be a delay between when a repository is added and when affected users gain access in Sourcebot (up to the `experiment_userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).
These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all private repositories accessible to each authenticated user. However, there may be a delay between when a repository is added and when affected users gain access in Sourcebot (up to the `userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).

If your workspace relies heavily on group or project-level permissions rather than direct user grants, we recommend reducing the `experiment_userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
If your workspace relies heavily on group or project-level permissions rather than direct user grants, we recommend reducing the `userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
</Warning>

**Notes:**
Expand All@@ -120,16 +120,64 @@ Permission syncing works with **Bitbucket Data Center**. OAuth tokens must assum
- Project-level permissions (inherited by all repos in the project)
- Group membership

These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all repositories accessible to each authenticated user using the `REPO_READ` scope. However, there may be a delay between when access is granted and when affected users see the repository in Sourcebot (up to the `experiment_userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).
These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all repositories accessible to each authenticated user using the `REPO_READ` scope. However, there may be a delay between when access is granted and when affected users see the repository in Sourcebot (up to the `userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).

If your instance relies heavily on project or group-level permissions, we recommend reducing the `experiment_userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
If your instance relies heavily on project or group-level permissions, we recommend reducing the `userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
</Warning>

**Notes:**
- A Bitbucket Data Center [external identity provider](/docs/configuration/idp#bitbucket-server) must be configured to (1) correlate a Sourcebot user with a Bitbucket Data Center user, and (2) to list repositories that the user has access to for [User driven syncing](/docs/features/permission-syncing#how-it-works).
- The connection token must have **Repository Read** permissions so Sourcebot can read repository-level user permissions for [Repo driven syncing](/docs/features/permission-syncing#how-it-works).
- OAuth tokens require the `REPO_READ` scope to list accessible repositories during [User driven syncing](/docs/features/permission-syncing#how-it-works).

# Manually refreshing permissions

If a user's permissions have changed and they need access updated immediately (without waiting for the next scheduled sync), they can trigger a manual refresh from the **Linked Accounts** page:

1. Navigate to **Settings → Linked Accounts**.
2. Click the **Connected** button next to the relevant code host account.
3. Select **Refresh Permissions** from the dropdown.

<Frame>
<img src="/images/linked_accounts_refresh_permissions.png" alt="Linked Accounts - Refresh Permissions" />
</Frame>

The button will show a spinner while the sync is in progress and display a confirmation once it completes.


# Overriding enforcement per connection

Each [connection](/docs/connections/overview) supports an `enforcePermissions` flag that controls whether permissions are enforced for repositories in that connection. This lets you mix code hosts in a single deployment - for example, enforcing access control on a private GitHub connection while keeping an internal Gerrit instance open to all users.

By default, `enforcePermissions` inherits the value of `PERMISSION_SYNC_ENABLED`. You can override it per connection in the [config file](/docs/configuration/config-file):

```json
{
"connections": {
"my-github": {
"type": "github",
"enforcePermissions": true
},
"my-gerrit": {
"type": "gerrit",
"url": "https://gerrit.example.com",
"enforcePermissions": false
}
}
}
```

Setting `enforcePermissions: false` on a connection makes all repositories from that connection accessible to any user, regardless of the global `PERMISSION_SYNC_ENABLED` setting.

The table below shows when permissions are enforced based on the combination of `PERMISSION_SYNC_ENABLED` and `enforcePermissions`:

| `PERMISSION_SYNC_ENABLED` | `enforcePermissions` | Permissions enforced? |
|--------------------------|---------------------|-----------------------|
| `true` | `true` | Yes |
| `true` | `false` | No |
| `false` | `true` | No |
| `false` | `false` | No |
Comment thread
brendan-kellam marked this conversation as resolved.

# How it works

Permission syncing works by periodically syncing ACLs from the code host(s) to Sourcebot to build an internal mapping between Users and Repositories. This mapping is hydrated in two directions:
Expand All@@ -146,19 +194,5 @@ The sync intervals can be configured using the following settings in the [config

| Setting | Type | Default | Minimum |
|-------------------------------------------------|---------|------------|---------|
| `experiment_repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |
| `experiment_userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |

## Manually refreshing permissions

If a user's permissions have changed and they need access updated immediately (without waiting for the next scheduled sync), they can trigger a manual refresh from the **Linked Accounts** page:

1. Navigate to **Settings → Linked Accounts**.
2. Click the **Connected** button next to the relevant code host account.
3. Select **Refresh Permissions** from the dropdown.

<Frame>
<img src="/images/linked_accounts_refresh_permissions.png" alt="Linked Accounts - Refresh Permissions" />
</Frame>

The button will show a spinner while the sync is in progress and display a confirmation once it completes.
| `repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |
| `userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/azuredevops.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -189,6 +189,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/bitbucket.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -162,6 +162,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
28 changes: 28 additions & 0 deletions docs/snippets/schemas/v3/connection.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -205,6 +205,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -407,6 +411,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -562,6 +570,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -669,6 +681,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -839,6 +855,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -1047,6 +1067,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -1116,6 +1140,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/genericGitHost.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -60,6 +60,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/gerrit.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -100,6 +100,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/gitea.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -148,6 +148,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/github.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -201,6 +201,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/gitlab.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -195,6 +195,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,6 +10,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- [EE] Added multi-owner support with promote/demote actions. [#988](https://github.com/sourcebot-dev/sourcebot/pull/988)
- [EE] Added `PERMISSION_SYNC_REPO_DRIVEN_ENABLED` environment variable to enable/disable repo-driven permission syncing. [#989](https://github.com/sourcebot-dev/sourcebot/pull/989)
- [EE] Added `enforcePermissions` per-connection flag to control whether repository permissions are enforced for a given connection. Defaults to the value of `PERMISSION_SYNC_ENABLED`. [#991](https://github.com/sourcebot-dev/sourcebot/pull/991)
- [EE] Added `repoDrivenPermissionSyncIntervalMs` and `userDrivenPermissionSyncIntervalMs` config settings, deprecating the `experiment_` prefixed variants (still respected as fallbacks). [#991](https://github.com/sourcebot-dev/sourcebot/pull/991)

### Changed
- [EE] Promoted `PERMISSION_SYNC_ENABLED` as the canonical env var for enabling permission syncing, deprecating `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` (still respected as a fallback). [#991](https://github.com/sourcebot-dev/sourcebot/pull/991)

## [4.15.3] - 2026-03-10

Expand Down
6 changes: 4 additions & 2 deletions docs/docs/configuration/config-file.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -50,8 +50,10 @@ The following are settings that can be provided in your config file to modify So
| `repoGarbageCollectionGracePeriodMs` | number | 10 seconds | 1 | Grace period to avoid deleting shards while loading. |
| `repoIndexTimeoutMs` | number | 2 hours | 1 | Timeout for a single repo‑indexing run. |
| `enablePublicAccess` **(deprecated)** | boolean | false | — | Use the `FORCE_ENABLE_ANONYMOUS_ACCESS` environment variable instead. |
| `experiment_repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the repo permission syncer should run. |
| `experiment_userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the user permission syncer should run. |
| `repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the repo permission syncer should run. |
| `userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the user permission syncer should run. |
| `experiment_repoDrivenPermissionSyncIntervalMs` **(deprecated)** | number | 24 hours | 1 | Use `repoDrivenPermissionSyncIntervalMs` instead. |
| `experiment_userDrivenPermissionSyncIntervalMs` **(deprecated)** | number | 24 hours | 1 | Use `userDrivenPermissionSyncIntervalMs` instead. |
Comment thread
brendan-kellam marked this conversation as resolved.
| `maxAccountPermissionSyncJobConcurrency` | number | 8 | 1 | Concurrent account permission sync jobs. |
| `maxRepoPermissionSyncJobConcurrency` | number | 8 | 1 | Concurrent repo permission sync jobs. |

Expand Down
5 changes: 3 additions & 2 deletions docs/docs/configuration/environment-variables.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -45,8 +45,9 @@ The following environment variables allow you to configure your Sourcebot deploy
| `SOURCEBOT_EE_AUDIT_RETENTION_DAYS` | `180` | <p>The number of days to retain audit logs. Audit log records older than this will be automatically pruned daily. Set to `0` to disable pruning and retain logs indefinitely.</p> |
| `AUTH_EE_GCP_IAP_ENABLED` | `false` | <p>When enabled, allows Sourcebot to automatically register/login from a successful GCP IAP redirect</p> |
| `AUTH_EE_GCP_IAP_AUDIENCE` | - | <p>The GCP IAP audience to use when verifying JWT tokens. Must be set to enable GCP IAP JIT provisioning</p> |
| `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` | `false` | <p>Enables [permission syncing](/docs/features/permission-syncing).</p> |
| `PERMISSION_SYNC_REPO_DRIVEN_ENABLED` | `true` | <p>Enables/disables [repo-driven permission syncing](/docs/features/permission-syncing#how-it-works). Only applies when `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` is `true`.</p> |
| `PERMISSION_SYNC_ENABLED` | `false` | <p>Enables [permission syncing](/docs/features/permission-syncing).</p> |
| `PERMISSION_SYNC_REPO_DRIVEN_ENABLED` | `true` | <p>Enables/disables [repo-driven permission syncing](/docs/features/permission-syncing#how-it-works). Only applies when `PERMISSION_SYNC_ENABLED` is `true`.</p> |
Comment thread
brendan-kellam marked this conversation as resolved.
| `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` **(deprecated)** | `false` | <p>Deprecated. Use `PERMISSION_SYNC_ENABLED` instead.</p> |
| `AUTH_EE_ALLOW_EMAIL_ACCOUNT_LINKING` | `true` | <p>When enabled, different SSO accounts with the same email address will automatically be linked.</p> |


Expand Down
78 changes: 56 additions & 22 deletions docs/docs/features/permission-syncing.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,11 +18,11 @@ that they have access to on the code host. Practically, this means:
- Ask Sourcebot (and the underlying LLM) will only have access to repositories that the user has access to.
- File browsing is scoped to the repositories that the user has access to.

Permission syncing can be enabled by setting the `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` environment variable to `true`.
Permission syncing can be enabled by setting the `PERMISSION_SYNC_ENABLED` environment variable to `true`.

```bash
docker run \
-e EXPERIMENT_EE_PERMISSION_SYNC_ENABLED=true \
-e PERMISSION_SYNC_ENABLED=true \
/* additional args */ \
ghcr.io/sourcebot-dev/sourcebot:latest
```
Expand DownExpand Up@@ -97,9 +97,9 @@ Permission syncing works with **Bitbucket Cloud**. OAuth tokens must assume the
- Membership in the [project that contains the repository](https://support.atlassian.com/bitbucket-cloud/docs/configure-project-permissions-for-users-and-groups/)
- Membership in a group that is part of a project containing the repository

These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all private repositories accessible to each authenticated user. However, there may be a delay between when a repository is added and when affected users gain access in Sourcebot (up to the `experiment_userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).
These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all private repositories accessible to each authenticated user. However, there may be a delay between when a repository is added and when affected users gain access in Sourcebot (up to the `userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).

If your workspace relies heavily on group or project-level permissions rather than direct user grants, we recommend reducing the `experiment_userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
If your workspace relies heavily on group or project-level permissions rather than direct user grants, we recommend reducing the `userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
</Warning>

**Notes:**
Expand All@@ -120,16 +120,64 @@ Permission syncing works with **Bitbucket Data Center**. OAuth tokens must assum
- Project-level permissions (inherited by all repos in the project)
- Group membership

These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all repositories accessible to each authenticated user using the `REPO_READ` scope. However, there may be a delay between when access is granted and when affected users see the repository in Sourcebot (up to the `experiment_userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).
These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all repositories accessible to each authenticated user using the `REPO_READ` scope. However, there may be a delay between when access is granted and when affected users see the repository in Sourcebot (up to the `userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).

If your instance relies heavily on project or group-level permissions, we recommend reducing the `experiment_userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
If your instance relies heavily on project or group-level permissions, we recommend reducing the `userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
</Warning>

**Notes:**
- A Bitbucket Data Center [external identity provider](/docs/configuration/idp#bitbucket-server) must be configured to (1) correlate a Sourcebot user with a Bitbucket Data Center user, and (2) to list repositories that the user has access to for [User driven syncing](/docs/features/permission-syncing#how-it-works).
- The connection token must have **Repository Read** permissions so Sourcebot can read repository-level user permissions for [Repo driven syncing](/docs/features/permission-syncing#how-it-works).
- OAuth tokens require the `REPO_READ` scope to list accessible repositories during [User driven syncing](/docs/features/permission-syncing#how-it-works).

# Manually refreshing permissions

If a user's permissions have changed and they need access updated immediately (without waiting for the next scheduled sync), they can trigger a manual refresh from the **Linked Accounts** page:

1. Navigate to **Settings → Linked Accounts**.
2. Click the **Connected** button next to the relevant code host account.
3. Select **Refresh Permissions** from the dropdown.

<Frame>
<img src="/images/linked_accounts_refresh_permissions.png" alt="Linked Accounts - Refresh Permissions" />
</Frame>

The button will show a spinner while the sync is in progress and display a confirmation once it completes.


# Overriding enforcement per connection

Each [connection](/docs/connections/overview) supports an `enforcePermissions` flag that controls whether permissions are enforced for repositories in that connection. This lets you mix code hosts in a single deployment - for example, enforcing access control on a private GitHub connection while keeping an internal Gerrit instance open to all users.

By default, `enforcePermissions` inherits the value of `PERMISSION_SYNC_ENABLED`. You can override it per connection in the [config file](/docs/configuration/config-file):

```json
{
"connections": {
"my-github": {
"type": "github",
"enforcePermissions": true
},
"my-gerrit": {
"type": "gerrit",
"url": "https://gerrit.example.com",
"enforcePermissions": false
}
}
}
```

Setting `enforcePermissions: false` on a connection makes all repositories from that connection accessible to any user, regardless of the global `PERMISSION_SYNC_ENABLED` setting.

The table below shows when permissions are enforced based on the combination of `PERMISSION_SYNC_ENABLED` and `enforcePermissions`:

| `PERMISSION_SYNC_ENABLED` | `enforcePermissions` | Permissions enforced? |
|--------------------------|---------------------|-----------------------|
| `true` | `true` | Yes |
| `true` | `false` | No |
| `false` | `true` | No |
| `false` | `false` | No |
Comment thread
brendan-kellam marked this conversation as resolved.

# How it works

Permission syncing works by periodically syncing ACLs from the code host(s) to Sourcebot to build an internal mapping between Users and Repositories. This mapping is hydrated in two directions:
Expand All@@ -146,19 +194,5 @@ The sync intervals can be configured using the following settings in the [config

| Setting | Type | Default | Minimum |
|-------------------------------------------------|---------|------------|---------|
| `experiment_repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |
| `experiment_userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |

## Manually refreshing permissions

If a user's permissions have changed and they need access updated immediately (without waiting for the next scheduled sync), they can trigger a manual refresh from the **Linked Accounts** page:

1. Navigate to **Settings → Linked Accounts**.
2. Click the **Connected** button next to the relevant code host account.
3. Select **Refresh Permissions** from the dropdown.

<Frame>
<img src="/images/linked_accounts_refresh_permissions.png" alt="Linked Accounts - Refresh Permissions" />
</Frame>

The button will show a spinner while the sync is in progress and display a confirmation once it completes.
| `repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |
| `userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/azuredevops.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -189,6 +189,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/bitbucket.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -162,6 +162,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
28 changes: 28 additions & 0 deletions docs/snippets/schemas/v3/connection.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -205,6 +205,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -407,6 +411,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -562,6 +570,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -669,6 +681,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -839,6 +855,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -1047,6 +1067,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -1116,6 +1140,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/genericGitHost.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -60,6 +60,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/gerrit.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -100,6 +100,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/gitea.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -148,6 +148,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/github.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -201,6 +201,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/gitlab.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -195,6 +195,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,6 +10,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- [EE] Added multi-owner support with promote/demote actions. [#988](https://github.com/sourcebot-dev/sourcebot/pull/988)
- [EE] Added `PERMISSION_SYNC_REPO_DRIVEN_ENABLED` environment variable to enable/disable repo-driven permission syncing. [#989](https://github.com/sourcebot-dev/sourcebot/pull/989)
- [EE] Added `enforcePermissions` per-connection flag to control whether repository permissions are enforced for a given connection. Defaults to the value of `PERMISSION_SYNC_ENABLED`. [#991](https://github.com/sourcebot-dev/sourcebot/pull/991)
- [EE] Added `repoDrivenPermissionSyncIntervalMs` and `userDrivenPermissionSyncIntervalMs` config settings, deprecating the `experiment_` prefixed variants (still respected as fallbacks). [#991](https://github.com/sourcebot-dev/sourcebot/pull/991)

### Changed
- [EE] Promoted `PERMISSION_SYNC_ENABLED` as the canonical env var for enabling permission syncing, deprecating `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` (still respected as a fallback). [#991](https://github.com/sourcebot-dev/sourcebot/pull/991)

## [4.15.3] - 2026-03-10

Expand Down
6 changes: 4 additions & 2 deletions docs/docs/configuration/config-file.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -50,8 +50,10 @@ The following are settings that can be provided in your config file to modify So
| `repoGarbageCollectionGracePeriodMs` | number | 10 seconds | 1 | Grace period to avoid deleting shards while loading. |
| `repoIndexTimeoutMs` | number | 2 hours | 1 | Timeout for a single repo‑indexing run. |
| `enablePublicAccess` **(deprecated)** | boolean | false | — | Use the `FORCE_ENABLE_ANONYMOUS_ACCESS` environment variable instead. |
| `experiment_repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the repo permission syncer should run. |
| `experiment_userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the user permission syncer should run. |
| `repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the repo permission syncer should run. |
| `userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the user permission syncer should run. |
| `experiment_repoDrivenPermissionSyncIntervalMs` **(deprecated)** | number | 24 hours | 1 | Use `repoDrivenPermissionSyncIntervalMs` instead. |
| `experiment_userDrivenPermissionSyncIntervalMs` **(deprecated)** | number | 24 hours | 1 | Use `userDrivenPermissionSyncIntervalMs` instead. |
Comment thread
brendan-kellam marked this conversation as resolved.
| `maxAccountPermissionSyncJobConcurrency` | number | 8 | 1 | Concurrent account permission sync jobs. |
| `maxRepoPermissionSyncJobConcurrency` | number | 8 | 1 | Concurrent repo permission sync jobs. |

Expand Down
5 changes: 3 additions & 2 deletions docs/docs/configuration/environment-variables.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -45,8 +45,9 @@ The following environment variables allow you to configure your Sourcebot deploy
| `SOURCEBOT_EE_AUDIT_RETENTION_DAYS` | `180` | <p>The number of days to retain audit logs. Audit log records older than this will be automatically pruned daily. Set to `0` to disable pruning and retain logs indefinitely.</p> |
| `AUTH_EE_GCP_IAP_ENABLED` | `false` | <p>When enabled, allows Sourcebot to automatically register/login from a successful GCP IAP redirect</p> |
| `AUTH_EE_GCP_IAP_AUDIENCE` | - | <p>The GCP IAP audience to use when verifying JWT tokens. Must be set to enable GCP IAP JIT provisioning</p> |
| `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` | `false` | <p>Enables [permission syncing](/docs/features/permission-syncing).</p> |
| `PERMISSION_SYNC_REPO_DRIVEN_ENABLED` | `true` | <p>Enables/disables [repo-driven permission syncing](/docs/features/permission-syncing#how-it-works). Only applies when `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` is `true`.</p> |
| `PERMISSION_SYNC_ENABLED` | `false` | <p>Enables [permission syncing](/docs/features/permission-syncing).</p> |
| `PERMISSION_SYNC_REPO_DRIVEN_ENABLED` | `true` | <p>Enables/disables [repo-driven permission syncing](/docs/features/permission-syncing#how-it-works). Only applies when `PERMISSION_SYNC_ENABLED` is `true`.</p> |
Comment thread
brendan-kellam marked this conversation as resolved.
| `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` **(deprecated)** | `false` | <p>Deprecated. Use `PERMISSION_SYNC_ENABLED` instead.</p> |
| `AUTH_EE_ALLOW_EMAIL_ACCOUNT_LINKING` | `true` | <p>When enabled, different SSO accounts with the same email address will automatically be linked.</p> |


Expand Down
78 changes: 56 additions & 22 deletions docs/docs/features/permission-syncing.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,11 +18,11 @@ that they have access to on the code host. Practically, this means:
- Ask Sourcebot (and the underlying LLM) will only have access to repositories that the user has access to.
- File browsing is scoped to the repositories that the user has access to.

Permission syncing can be enabled by setting the `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` environment variable to `true`.
Permission syncing can be enabled by setting the `PERMISSION_SYNC_ENABLED` environment variable to `true`.

```bash
docker run \
-e EXPERIMENT_EE_PERMISSION_SYNC_ENABLED=true \
-e PERMISSION_SYNC_ENABLED=true \
/* additional args */ \
ghcr.io/sourcebot-dev/sourcebot:latest
```
Expand DownExpand Up@@ -97,9 +97,9 @@ Permission syncing works with **Bitbucket Cloud**. OAuth tokens must assume the
- Membership in the [project that contains the repository](https://support.atlassian.com/bitbucket-cloud/docs/configure-project-permissions-for-users-and-groups/)
- Membership in a group that is part of a project containing the repository

These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all private repositories accessible to each authenticated user. However, there may be a delay between when a repository is added and when affected users gain access in Sourcebot (up to the `experiment_userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).
These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all private repositories accessible to each authenticated user. However, there may be a delay between when a repository is added and when affected users gain access in Sourcebot (up to the `userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).

If your workspace relies heavily on group or project-level permissions rather than direct user grants, we recommend reducing the `experiment_userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
If your workspace relies heavily on group or project-level permissions rather than direct user grants, we recommend reducing the `userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
</Warning>

**Notes:**
Expand All@@ -120,16 +120,64 @@ Permission syncing works with **Bitbucket Data Center**. OAuth tokens must assum
- Project-level permissions (inherited by all repos in the project)
- Group membership

These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all repositories accessible to each authenticated user using the `REPO_READ` scope. However, there may be a delay between when access is granted and when affected users see the repository in Sourcebot (up to the `experiment_userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).
These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all repositories accessible to each authenticated user using the `REPO_READ` scope. However, there may be a delay between when access is granted and when affected users see the repository in Sourcebot (up to the `userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).

If your instance relies heavily on project or group-level permissions, we recommend reducing the `experiment_userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
If your instance relies heavily on project or group-level permissions, we recommend reducing the `userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
</Warning>

**Notes:**
- A Bitbucket Data Center [external identity provider](/docs/configuration/idp#bitbucket-server) must be configured to (1) correlate a Sourcebot user with a Bitbucket Data Center user, and (2) to list repositories that the user has access to for [User driven syncing](/docs/features/permission-syncing#how-it-works).
- The connection token must have **Repository Read** permissions so Sourcebot can read repository-level user permissions for [Repo driven syncing](/docs/features/permission-syncing#how-it-works).
- OAuth tokens require the `REPO_READ` scope to list accessible repositories during [User driven syncing](/docs/features/permission-syncing#how-it-works).

# Manually refreshing permissions

If a user's permissions have changed and they need access updated immediately (without waiting for the next scheduled sync), they can trigger a manual refresh from the **Linked Accounts** page:

1. Navigate to **Settings → Linked Accounts**.
2. Click the **Connected** button next to the relevant code host account.
3. Select **Refresh Permissions** from the dropdown.

<Frame>
<img src="/images/linked_accounts_refresh_permissions.png" alt="Linked Accounts - Refresh Permissions" />
</Frame>

The button will show a spinner while the sync is in progress and display a confirmation once it completes.


# Overriding enforcement per connection

Each [connection](/docs/connections/overview) supports an `enforcePermissions` flag that controls whether permissions are enforced for repositories in that connection. This lets you mix code hosts in a single deployment - for example, enforcing access control on a private GitHub connection while keeping an internal Gerrit instance open to all users.

By default, `enforcePermissions` inherits the value of `PERMISSION_SYNC_ENABLED`. You can override it per connection in the [config file](/docs/configuration/config-file):

```json
{
"connections": {
"my-github": {
"type": "github",
"enforcePermissions": true
},
"my-gerrit": {
"type": "gerrit",
"url": "https://gerrit.example.com",
"enforcePermissions": false
}
}
}
```

Setting `enforcePermissions: false` on a connection makes all repositories from that connection accessible to any user, regardless of the global `PERMISSION_SYNC_ENABLED` setting.

The table below shows when permissions are enforced based on the combination of `PERMISSION_SYNC_ENABLED` and `enforcePermissions`:

| `PERMISSION_SYNC_ENABLED` | `enforcePermissions` | Permissions enforced? |
|--------------------------|---------------------|-----------------------|
| `true` | `true` | Yes |
| `true` | `false` | No |
| `false` | `true` | No |
| `false` | `false` | No |
Comment thread
brendan-kellam marked this conversation as resolved.

# How it works

Permission syncing works by periodically syncing ACLs from the code host(s) to Sourcebot to build an internal mapping between Users and Repositories. This mapping is hydrated in two directions:
Expand All@@ -146,19 +194,5 @@ The sync intervals can be configured using the following settings in the [config

| Setting | Type | Default | Minimum |
|-------------------------------------------------|---------|------------|---------|
| `experiment_repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |
| `experiment_userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |

## Manually refreshing permissions

If a user's permissions have changed and they need access updated immediately (without waiting for the next scheduled sync), they can trigger a manual refresh from the **Linked Accounts** page:

1. Navigate to **Settings → Linked Accounts**.
2. Click the **Connected** button next to the relevant code host account.
3. Select **Refresh Permissions** from the dropdown.

<Frame>
<img src="/images/linked_accounts_refresh_permissions.png" alt="Linked Accounts - Refresh Permissions" />
</Frame>

The button will show a spinner while the sync is in progress and display a confirmation once it completes.
| `repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |
| `userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/azuredevops.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -189,6 +189,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/bitbucket.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -162,6 +162,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
28 changes: 28 additions & 0 deletions docs/snippets/schemas/v3/connection.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -205,6 +205,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -407,6 +411,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -562,6 +570,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -669,6 +681,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -839,6 +855,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -1047,6 +1067,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -1116,6 +1140,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/genericGitHost.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -60,6 +60,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/gerrit.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -100,6 +100,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/gitea.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -148,6 +148,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/github.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -201,6 +201,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/gitlab.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -195,6 +195,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,6 +10,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- [EE] Added multi-owner support with promote/demote actions. [#988](https://github.com/sourcebot-dev/sourcebot/pull/988)
- [EE] Added `PERMISSION_SYNC_REPO_DRIVEN_ENABLED` environment variable to enable/disable repo-driven permission syncing. [#989](https://github.com/sourcebot-dev/sourcebot/pull/989)
- [EE] Added `enforcePermissions` per-connection flag to control whether repository permissions are enforced for a given connection. Defaults to the value of `PERMISSION_SYNC_ENABLED`. [#991](https://github.com/sourcebot-dev/sourcebot/pull/991)
- [EE] Added `repoDrivenPermissionSyncIntervalMs` and `userDrivenPermissionSyncIntervalMs` config settings, deprecating the `experiment_` prefixed variants (still respected as fallbacks). [#991](https://github.com/sourcebot-dev/sourcebot/pull/991)

### Changed
- [EE] Promoted `PERMISSION_SYNC_ENABLED` as the canonical env var for enabling permission syncing, deprecating `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` (still respected as a fallback). [#991](https://github.com/sourcebot-dev/sourcebot/pull/991)

## [4.15.3] - 2026-03-10

Expand Down
6 changes: 4 additions & 2 deletions docs/docs/configuration/config-file.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -50,8 +50,10 @@ The following are settings that can be provided in your config file to modify So
| `repoGarbageCollectionGracePeriodMs` | number | 10 seconds | 1 | Grace period to avoid deleting shards while loading. |
| `repoIndexTimeoutMs` | number | 2 hours | 1 | Timeout for a single repo‑indexing run. |
| `enablePublicAccess` **(deprecated)** | boolean | false | — | Use the `FORCE_ENABLE_ANONYMOUS_ACCESS` environment variable instead. |
| `experiment_repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the repo permission syncer should run. |
| `experiment_userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the user permission syncer should run. |
| `repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the repo permission syncer should run. |
| `userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the user permission syncer should run. |
| `experiment_repoDrivenPermissionSyncIntervalMs` **(deprecated)** | number | 24 hours | 1 | Use `repoDrivenPermissionSyncIntervalMs` instead. |
| `experiment_userDrivenPermissionSyncIntervalMs` **(deprecated)** | number | 24 hours | 1 | Use `userDrivenPermissionSyncIntervalMs` instead. |
Comment thread
brendan-kellam marked this conversation as resolved.
| `maxAccountPermissionSyncJobConcurrency` | number | 8 | 1 | Concurrent account permission sync jobs. |
| `maxRepoPermissionSyncJobConcurrency` | number | 8 | 1 | Concurrent repo permission sync jobs. |

Expand Down
5 changes: 3 additions & 2 deletions docs/docs/configuration/environment-variables.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -45,8 +45,9 @@ The following environment variables allow you to configure your Sourcebot deploy
| `SOURCEBOT_EE_AUDIT_RETENTION_DAYS` | `180` | <p>The number of days to retain audit logs. Audit log records older than this will be automatically pruned daily. Set to `0` to disable pruning and retain logs indefinitely.</p> |
| `AUTH_EE_GCP_IAP_ENABLED` | `false` | <p>When enabled, allows Sourcebot to automatically register/login from a successful GCP IAP redirect</p> |
| `AUTH_EE_GCP_IAP_AUDIENCE` | - | <p>The GCP IAP audience to use when verifying JWT tokens. Must be set to enable GCP IAP JIT provisioning</p> |
| `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` | `false` | <p>Enables [permission syncing](/docs/features/permission-syncing).</p> |
| `PERMISSION_SYNC_REPO_DRIVEN_ENABLED` | `true` | <p>Enables/disables [repo-driven permission syncing](/docs/features/permission-syncing#how-it-works). Only applies when `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` is `true`.</p> |
| `PERMISSION_SYNC_ENABLED` | `false` | <p>Enables [permission syncing](/docs/features/permission-syncing).</p> |
| `PERMISSION_SYNC_REPO_DRIVEN_ENABLED` | `true` | <p>Enables/disables [repo-driven permission syncing](/docs/features/permission-syncing#how-it-works). Only applies when `PERMISSION_SYNC_ENABLED` is `true`.</p> |
Comment thread
brendan-kellam marked this conversation as resolved.
| `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` **(deprecated)** | `false` | <p>Deprecated. Use `PERMISSION_SYNC_ENABLED` instead.</p> |
| `AUTH_EE_ALLOW_EMAIL_ACCOUNT_LINKING` | `true` | <p>When enabled, different SSO accounts with the same email address will automatically be linked.</p> |


Expand Down
78 changes: 56 additions & 22 deletions docs/docs/features/permission-syncing.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,11 +18,11 @@ that they have access to on the code host. Practically, this means:
- Ask Sourcebot (and the underlying LLM) will only have access to repositories that the user has access to.
- File browsing is scoped to the repositories that the user has access to.

Permission syncing can be enabled by setting the `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` environment variable to `true`.
Permission syncing can be enabled by setting the `PERMISSION_SYNC_ENABLED` environment variable to `true`.

```bash
docker run \
-e EXPERIMENT_EE_PERMISSION_SYNC_ENABLED=true \
-e PERMISSION_SYNC_ENABLED=true \
/* additional args */ \
ghcr.io/sourcebot-dev/sourcebot:latest
```
Expand DownExpand Up@@ -97,9 +97,9 @@ Permission syncing works with **Bitbucket Cloud**. OAuth tokens must assume the
- Membership in the [project that contains the repository](https://support.atlassian.com/bitbucket-cloud/docs/configure-project-permissions-for-users-and-groups/)
- Membership in a group that is part of a project containing the repository

These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all private repositories accessible to each authenticated user. However, there may be a delay between when a repository is added and when affected users gain access in Sourcebot (up to the `experiment_userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).
These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all private repositories accessible to each authenticated user. However, there may be a delay between when a repository is added and when affected users gain access in Sourcebot (up to the `userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).

If your workspace relies heavily on group or project-level permissions rather than direct user grants, we recommend reducing the `experiment_userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
If your workspace relies heavily on group or project-level permissions rather than direct user grants, we recommend reducing the `userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
</Warning>

**Notes:**
Expand All@@ -120,16 +120,64 @@ Permission syncing works with **Bitbucket Data Center**. OAuth tokens must assum
- Project-level permissions (inherited by all repos in the project)
- Group membership

These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all repositories accessible to each authenticated user using the `REPO_READ` scope. However, there may be a delay between when access is granted and when affected users see the repository in Sourcebot (up to the `experiment_userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).
These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all repositories accessible to each authenticated user using the `REPO_READ` scope. However, there may be a delay between when access is granted and when affected users see the repository in Sourcebot (up to the `userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).

If your instance relies heavily on project or group-level permissions, we recommend reducing the `experiment_userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
If your instance relies heavily on project or group-level permissions, we recommend reducing the `userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
</Warning>

**Notes:**
- A Bitbucket Data Center [external identity provider](/docs/configuration/idp#bitbucket-server) must be configured to (1) correlate a Sourcebot user with a Bitbucket Data Center user, and (2) to list repositories that the user has access to for [User driven syncing](/docs/features/permission-syncing#how-it-works).
- The connection token must have **Repository Read** permissions so Sourcebot can read repository-level user permissions for [Repo driven syncing](/docs/features/permission-syncing#how-it-works).
- OAuth tokens require the `REPO_READ` scope to list accessible repositories during [User driven syncing](/docs/features/permission-syncing#how-it-works).

# Manually refreshing permissions

If a user's permissions have changed and they need access updated immediately (without waiting for the next scheduled sync), they can trigger a manual refresh from the **Linked Accounts** page:

1. Navigate to **Settings → Linked Accounts**.
2. Click the **Connected** button next to the relevant code host account.
3. Select **Refresh Permissions** from the dropdown.

<Frame>
<img src="/images/linked_accounts_refresh_permissions.png" alt="Linked Accounts - Refresh Permissions" />
</Frame>

The button will show a spinner while the sync is in progress and display a confirmation once it completes.


# Overriding enforcement per connection

Each [connection](/docs/connections/overview) supports an `enforcePermissions` flag that controls whether permissions are enforced for repositories in that connection. This lets you mix code hosts in a single deployment - for example, enforcing access control on a private GitHub connection while keeping an internal Gerrit instance open to all users.

By default, `enforcePermissions` inherits the value of `PERMISSION_SYNC_ENABLED`. You can override it per connection in the [config file](/docs/configuration/config-file):

```json
{
"connections": {
"my-github": {
"type": "github",
"enforcePermissions": true
},
"my-gerrit": {
"type": "gerrit",
"url": "https://gerrit.example.com",
"enforcePermissions": false
}
}
}
```

Setting `enforcePermissions: false` on a connection makes all repositories from that connection accessible to any user, regardless of the global `PERMISSION_SYNC_ENABLED` setting.

The table below shows when permissions are enforced based on the combination of `PERMISSION_SYNC_ENABLED` and `enforcePermissions`:

| `PERMISSION_SYNC_ENABLED` | `enforcePermissions` | Permissions enforced? |
|--------------------------|---------------------|-----------------------|
| `true` | `true` | Yes |
| `true` | `false` | No |
| `false` | `true` | No |
| `false` | `false` | No |
Comment thread
brendan-kellam marked this conversation as resolved.

# How it works

Permission syncing works by periodically syncing ACLs from the code host(s) to Sourcebot to build an internal mapping between Users and Repositories. This mapping is hydrated in two directions:
Expand All@@ -146,19 +194,5 @@ The sync intervals can be configured using the following settings in the [config

| Setting | Type | Default | Minimum |
|-------------------------------------------------|---------|------------|---------|
| `experiment_repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |
| `experiment_userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |

## Manually refreshing permissions

If a user's permissions have changed and they need access updated immediately (without waiting for the next scheduled sync), they can trigger a manual refresh from the **Linked Accounts** page:

1. Navigate to **Settings → Linked Accounts**.
2. Click the **Connected** button next to the relevant code host account.
3. Select **Refresh Permissions** from the dropdown.

<Frame>
<img src="/images/linked_accounts_refresh_permissions.png" alt="Linked Accounts - Refresh Permissions" />
</Frame>

The button will show a spinner while the sync is in progress and display a confirmation once it completes.
| `repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |
| `userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/azuredevops.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -189,6 +189,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/bitbucket.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -162,6 +162,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
28 changes: 28 additions & 0 deletions docs/snippets/schemas/v3/connection.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -205,6 +205,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -407,6 +411,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -562,6 +570,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -669,6 +681,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -839,6 +855,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -1047,6 +1067,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -1116,6 +1140,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/genericGitHost.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -60,6 +60,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/gerrit.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -100,6 +100,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/gitea.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -148,6 +148,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/github.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -201,6 +201,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/gitlab.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -195,6 +195,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,6 +10,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- [EE] Added multi-owner support with promote/demote actions. [#988](https://github.com/sourcebot-dev/sourcebot/pull/988)
- [EE] Added `PERMISSION_SYNC_REPO_DRIVEN_ENABLED` environment variable to enable/disable repo-driven permission syncing. [#989](https://github.com/sourcebot-dev/sourcebot/pull/989)
- [EE] Added `enforcePermissions` per-connection flag to control whether repository permissions are enforced for a given connection. Defaults to the value of `PERMISSION_SYNC_ENABLED`. [#991](https://github.com/sourcebot-dev/sourcebot/pull/991)
- [EE] Added `repoDrivenPermissionSyncIntervalMs` and `userDrivenPermissionSyncIntervalMs` config settings, deprecating the `experiment_` prefixed variants (still respected as fallbacks). [#991](https://github.com/sourcebot-dev/sourcebot/pull/991)

### Changed
- [EE] Promoted `PERMISSION_SYNC_ENABLED` as the canonical env var for enabling permission syncing, deprecating `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` (still respected as a fallback). [#991](https://github.com/sourcebot-dev/sourcebot/pull/991)

## [4.15.3] - 2026-03-10

Expand Down
6 changes: 4 additions & 2 deletions docs/docs/configuration/config-file.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -50,8 +50,10 @@ The following are settings that can be provided in your config file to modify So
| `repoGarbageCollectionGracePeriodMs` | number | 10 seconds | 1 | Grace period to avoid deleting shards while loading. |
| `repoIndexTimeoutMs` | number | 2 hours | 1 | Timeout for a single repo‑indexing run. |
| `enablePublicAccess` **(deprecated)** | boolean | false | — | Use the `FORCE_ENABLE_ANONYMOUS_ACCESS` environment variable instead. |
| `experiment_repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the repo permission syncer should run. |
| `experiment_userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the user permission syncer should run. |
| `repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the repo permission syncer should run. |
| `userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the user permission syncer should run. |
| `experiment_repoDrivenPermissionSyncIntervalMs` **(deprecated)** | number | 24 hours | 1 | Use `repoDrivenPermissionSyncIntervalMs` instead. |
| `experiment_userDrivenPermissionSyncIntervalMs` **(deprecated)** | number | 24 hours | 1 | Use `userDrivenPermissionSyncIntervalMs` instead. |
Comment thread
brendan-kellam marked this conversation as resolved.
| `maxAccountPermissionSyncJobConcurrency` | number | 8 | 1 | Concurrent account permission sync jobs. |
| `maxRepoPermissionSyncJobConcurrency` | number | 8 | 1 | Concurrent repo permission sync jobs. |

Expand Down
5 changes: 3 additions & 2 deletions docs/docs/configuration/environment-variables.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -45,8 +45,9 @@ The following environment variables allow you to configure your Sourcebot deploy
| `SOURCEBOT_EE_AUDIT_RETENTION_DAYS` | `180` | <p>The number of days to retain audit logs. Audit log records older than this will be automatically pruned daily. Set to `0` to disable pruning and retain logs indefinitely.</p> |
| `AUTH_EE_GCP_IAP_ENABLED` | `false` | <p>When enabled, allows Sourcebot to automatically register/login from a successful GCP IAP redirect</p> |
| `AUTH_EE_GCP_IAP_AUDIENCE` | - | <p>The GCP IAP audience to use when verifying JWT tokens. Must be set to enable GCP IAP JIT provisioning</p> |
| `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` | `false` | <p>Enables [permission syncing](/docs/features/permission-syncing).</p> |
| `PERMISSION_SYNC_REPO_DRIVEN_ENABLED` | `true` | <p>Enables/disables [repo-driven permission syncing](/docs/features/permission-syncing#how-it-works). Only applies when `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` is `true`.</p> |
| `PERMISSION_SYNC_ENABLED` | `false` | <p>Enables [permission syncing](/docs/features/permission-syncing).</p> |
| `PERMISSION_SYNC_REPO_DRIVEN_ENABLED` | `true` | <p>Enables/disables [repo-driven permission syncing](/docs/features/permission-syncing#how-it-works). Only applies when `PERMISSION_SYNC_ENABLED` is `true`.</p> |
Comment thread
brendan-kellam marked this conversation as resolved.
| `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` **(deprecated)** | `false` | <p>Deprecated. Use `PERMISSION_SYNC_ENABLED` instead.</p> |
| `AUTH_EE_ALLOW_EMAIL_ACCOUNT_LINKING` | `true` | <p>When enabled, different SSO accounts with the same email address will automatically be linked.</p> |


Expand Down
78 changes: 56 additions & 22 deletions docs/docs/features/permission-syncing.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,11 +18,11 @@ that they have access to on the code host. Practically, this means:
- Ask Sourcebot (and the underlying LLM) will only have access to repositories that the user has access to.
- File browsing is scoped to the repositories that the user has access to.

Permission syncing can be enabled by setting the `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` environment variable to `true`.
Permission syncing can be enabled by setting the `PERMISSION_SYNC_ENABLED` environment variable to `true`.

```bash
docker run \
-e EXPERIMENT_EE_PERMISSION_SYNC_ENABLED=true \
-e PERMISSION_SYNC_ENABLED=true \
/* additional args */ \
ghcr.io/sourcebot-dev/sourcebot:latest
```
Expand DownExpand Up@@ -97,9 +97,9 @@ Permission syncing works with **Bitbucket Cloud**. OAuth tokens must assume the
- Membership in the [project that contains the repository](https://support.atlassian.com/bitbucket-cloud/docs/configure-project-permissions-for-users-and-groups/)
- Membership in a group that is part of a project containing the repository

These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all private repositories accessible to each authenticated user. However, there may be a delay between when a repository is added and when affected users gain access in Sourcebot (up to the `experiment_userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).
These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all private repositories accessible to each authenticated user. However, there may be a delay between when a repository is added and when affected users gain access in Sourcebot (up to the `userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).

If your workspace relies heavily on group or project-level permissions rather than direct user grants, we recommend reducing the `experiment_userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
If your workspace relies heavily on group or project-level permissions rather than direct user grants, we recommend reducing the `userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
</Warning>

**Notes:**
Expand All@@ -120,16 +120,64 @@ Permission syncing works with **Bitbucket Data Center**. OAuth tokens must assum
- Project-level permissions (inherited by all repos in the project)
- Group membership

These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all repositories accessible to each authenticated user using the `REPO_READ` scope. However, there may be a delay between when access is granted and when affected users see the repository in Sourcebot (up to the `experiment_userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).
These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all repositories accessible to each authenticated user using the `REPO_READ` scope. However, there may be a delay between when access is granted and when affected users see the repository in Sourcebot (up to the `userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).

If your instance relies heavily on project or group-level permissions, we recommend reducing the `experiment_userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
If your instance relies heavily on project or group-level permissions, we recommend reducing the `userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
</Warning>

**Notes:**
- A Bitbucket Data Center [external identity provider](/docs/configuration/idp#bitbucket-server) must be configured to (1) correlate a Sourcebot user with a Bitbucket Data Center user, and (2) to list repositories that the user has access to for [User driven syncing](/docs/features/permission-syncing#how-it-works).
- The connection token must have **Repository Read** permissions so Sourcebot can read repository-level user permissions for [Repo driven syncing](/docs/features/permission-syncing#how-it-works).
- OAuth tokens require the `REPO_READ` scope to list accessible repositories during [User driven syncing](/docs/features/permission-syncing#how-it-works).

# Manually refreshing permissions

If a user's permissions have changed and they need access updated immediately (without waiting for the next scheduled sync), they can trigger a manual refresh from the **Linked Accounts** page:

1. Navigate to **Settings → Linked Accounts**.
2. Click the **Connected** button next to the relevant code host account.
3. Select **Refresh Permissions** from the dropdown.

<Frame>
<img src="/images/linked_accounts_refresh_permissions.png" alt="Linked Accounts - Refresh Permissions" />
</Frame>

The button will show a spinner while the sync is in progress and display a confirmation once it completes.


# Overriding enforcement per connection

Each [connection](/docs/connections/overview) supports an `enforcePermissions` flag that controls whether permissions are enforced for repositories in that connection. This lets you mix code hosts in a single deployment - for example, enforcing access control on a private GitHub connection while keeping an internal Gerrit instance open to all users.

By default, `enforcePermissions` inherits the value of `PERMISSION_SYNC_ENABLED`. You can override it per connection in the [config file](/docs/configuration/config-file):

```json
{
"connections": {
"my-github": {
"type": "github",
"enforcePermissions": true
},
"my-gerrit": {
"type": "gerrit",
"url": "https://gerrit.example.com",
"enforcePermissions": false
}
}
}
```

Setting `enforcePermissions: false` on a connection makes all repositories from that connection accessible to any user, regardless of the global `PERMISSION_SYNC_ENABLED` setting.

The table below shows when permissions are enforced based on the combination of `PERMISSION_SYNC_ENABLED` and `enforcePermissions`:

| `PERMISSION_SYNC_ENABLED` | `enforcePermissions` | Permissions enforced? |
|--------------------------|---------------------|-----------------------|
| `true` | `true` | Yes |
| `true` | `false` | No |
| `false` | `true` | No |
| `false` | `false` | No |
Comment thread
brendan-kellam marked this conversation as resolved.

# How it works

Permission syncing works by periodically syncing ACLs from the code host(s) to Sourcebot to build an internal mapping between Users and Repositories. This mapping is hydrated in two directions:
Expand All@@ -146,19 +194,5 @@ The sync intervals can be configured using the following settings in the [config

| Setting | Type | Default | Minimum |
|-------------------------------------------------|---------|------------|---------|
| `experiment_repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |
| `experiment_userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |

## Manually refreshing permissions

If a user's permissions have changed and they need access updated immediately (without waiting for the next scheduled sync), they can trigger a manual refresh from the **Linked Accounts** page:

1. Navigate to **Settings → Linked Accounts**.
2. Click the **Connected** button next to the relevant code host account.
3. Select **Refresh Permissions** from the dropdown.

<Frame>
<img src="/images/linked_accounts_refresh_permissions.png" alt="Linked Accounts - Refresh Permissions" />
</Frame>

The button will show a spinner while the sync is in progress and display a confirmation once it completes.
| `repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |
| `userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/azuredevops.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -189,6 +189,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/bitbucket.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -162,6 +162,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
28 changes: 28 additions & 0 deletions docs/snippets/schemas/v3/connection.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -205,6 +205,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -407,6 +411,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -562,6 +570,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -669,6 +681,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -839,6 +855,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -1047,6 +1067,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -1116,6 +1140,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/genericGitHost.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -60,6 +60,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/gerrit.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -100,6 +100,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/gitea.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -148,6 +148,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/github.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -201,6 +201,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/gitlab.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -195,6 +195,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,6 +10,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- [EE] Added multi-owner support with promote/demote actions. [#988](https://github.com/sourcebot-dev/sourcebot/pull/988)
- [EE] Added `PERMISSION_SYNC_REPO_DRIVEN_ENABLED` environment variable to enable/disable repo-driven permission syncing. [#989](https://github.com/sourcebot-dev/sourcebot/pull/989)
- [EE] Added `enforcePermissions` per-connection flag to control whether repository permissions are enforced for a given connection. Defaults to the value of `PERMISSION_SYNC_ENABLED`. [#991](https://github.com/sourcebot-dev/sourcebot/pull/991)
- [EE] Added `repoDrivenPermissionSyncIntervalMs` and `userDrivenPermissionSyncIntervalMs` config settings, deprecating the `experiment_` prefixed variants (still respected as fallbacks). [#991](https://github.com/sourcebot-dev/sourcebot/pull/991)

### Changed
- [EE] Promoted `PERMISSION_SYNC_ENABLED` as the canonical env var for enabling permission syncing, deprecating `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` (still respected as a fallback). [#991](https://github.com/sourcebot-dev/sourcebot/pull/991)

## [4.15.3] - 2026-03-10

Expand Down
6 changes: 4 additions & 2 deletions docs/docs/configuration/config-file.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -50,8 +50,10 @@ The following are settings that can be provided in your config file to modify So
| `repoGarbageCollectionGracePeriodMs` | number | 10 seconds | 1 | Grace period to avoid deleting shards while loading. |
| `repoIndexTimeoutMs` | number | 2 hours | 1 | Timeout for a single repo‑indexing run. |
| `enablePublicAccess` **(deprecated)** | boolean | false | — | Use the `FORCE_ENABLE_ANONYMOUS_ACCESS` environment variable instead. |
| `experiment_repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the repo permission syncer should run. |
| `experiment_userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the user permission syncer should run. |
| `repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the repo permission syncer should run. |
| `userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 | Interval at which the user permission syncer should run. |
| `experiment_repoDrivenPermissionSyncIntervalMs` **(deprecated)** | number | 24 hours | 1 | Use `repoDrivenPermissionSyncIntervalMs` instead. |
| `experiment_userDrivenPermissionSyncIntervalMs` **(deprecated)** | number | 24 hours | 1 | Use `userDrivenPermissionSyncIntervalMs` instead. |
Comment thread
brendan-kellam marked this conversation as resolved.
| `maxAccountPermissionSyncJobConcurrency` | number | 8 | 1 | Concurrent account permission sync jobs. |
| `maxRepoPermissionSyncJobConcurrency` | number | 8 | 1 | Concurrent repo permission sync jobs. |

Expand Down
5 changes: 3 additions & 2 deletions docs/docs/configuration/environment-variables.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -45,8 +45,9 @@ The following environment variables allow you to configure your Sourcebot deploy
| `SOURCEBOT_EE_AUDIT_RETENTION_DAYS` | `180` | <p>The number of days to retain audit logs. Audit log records older than this will be automatically pruned daily. Set to `0` to disable pruning and retain logs indefinitely.</p> |
| `AUTH_EE_GCP_IAP_ENABLED` | `false` | <p>When enabled, allows Sourcebot to automatically register/login from a successful GCP IAP redirect</p> |
| `AUTH_EE_GCP_IAP_AUDIENCE` | - | <p>The GCP IAP audience to use when verifying JWT tokens. Must be set to enable GCP IAP JIT provisioning</p> |
| `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` | `false` | <p>Enables [permission syncing](/docs/features/permission-syncing).</p> |
| `PERMISSION_SYNC_REPO_DRIVEN_ENABLED` | `true` | <p>Enables/disables [repo-driven permission syncing](/docs/features/permission-syncing#how-it-works). Only applies when `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` is `true`.</p> |
| `PERMISSION_SYNC_ENABLED` | `false` | <p>Enables [permission syncing](/docs/features/permission-syncing).</p> |
| `PERMISSION_SYNC_REPO_DRIVEN_ENABLED` | `true` | <p>Enables/disables [repo-driven permission syncing](/docs/features/permission-syncing#how-it-works). Only applies when `PERMISSION_SYNC_ENABLED` is `true`.</p> |
Comment thread
brendan-kellam marked this conversation as resolved.
| `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` **(deprecated)** | `false` | <p>Deprecated. Use `PERMISSION_SYNC_ENABLED` instead.</p> |
| `AUTH_EE_ALLOW_EMAIL_ACCOUNT_LINKING` | `true` | <p>When enabled, different SSO accounts with the same email address will automatically be linked.</p> |


Expand Down
78 changes: 56 additions & 22 deletions docs/docs/features/permission-syncing.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,11 +18,11 @@ that they have access to on the code host. Practically, this means:
- Ask Sourcebot (and the underlying LLM) will only have access to repositories that the user has access to.
- File browsing is scoped to the repositories that the user has access to.

Permission syncing can be enabled by setting the `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` environment variable to `true`.
Permission syncing can be enabled by setting the `PERMISSION_SYNC_ENABLED` environment variable to `true`.

```bash
docker run \
-e EXPERIMENT_EE_PERMISSION_SYNC_ENABLED=true \
-e PERMISSION_SYNC_ENABLED=true \
/* additional args */ \
ghcr.io/sourcebot-dev/sourcebot:latest
```
Expand DownExpand Up@@ -97,9 +97,9 @@ Permission syncing works with **Bitbucket Cloud**. OAuth tokens must assume the
- Membership in the [project that contains the repository](https://support.atlassian.com/bitbucket-cloud/docs/configure-project-permissions-for-users-and-groups/)
- Membership in a group that is part of a project containing the repository

These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all private repositories accessible to each authenticated user. However, there may be a delay between when a repository is added and when affected users gain access in Sourcebot (up to the `experiment_userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).
These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all private repositories accessible to each authenticated user. However, there may be a delay between when a repository is added and when affected users gain access in Sourcebot (up to the `userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).

If your workspace relies heavily on group or project-level permissions rather than direct user grants, we recommend reducing the `experiment_userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
If your workspace relies heavily on group or project-level permissions rather than direct user grants, we recommend reducing the `userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
</Warning>

**Notes:**
Expand All@@ -120,16 +120,64 @@ Permission syncing works with **Bitbucket Data Center**. OAuth tokens must assum
- Project-level permissions (inherited by all repos in the project)
- Group membership

These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all repositories accessible to each authenticated user using the `REPO_READ` scope. However, there may be a delay between when access is granted and when affected users see the repository in Sourcebot (up to the `experiment_userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).
These users **will** still gain access via [user-driven syncing](/docs/features/permission-syncing#how-it-works), which fetches all repositories accessible to each authenticated user using the `REPO_READ` scope. However, there may be a delay between when access is granted and when affected users see the repository in Sourcebot (up to the `userDrivenPermissionSyncIntervalMs` interval, which defaults to 24 hours).

If your instance relies heavily on project or group-level permissions, we recommend reducing the `experiment_userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
If your instance relies heavily on project or group-level permissions, we recommend reducing the `userDrivenPermissionSyncIntervalMs` interval to limit the window of delay.
</Warning>

**Notes:**
- A Bitbucket Data Center [external identity provider](/docs/configuration/idp#bitbucket-server) must be configured to (1) correlate a Sourcebot user with a Bitbucket Data Center user, and (2) to list repositories that the user has access to for [User driven syncing](/docs/features/permission-syncing#how-it-works).
- The connection token must have **Repository Read** permissions so Sourcebot can read repository-level user permissions for [Repo driven syncing](/docs/features/permission-syncing#how-it-works).
- OAuth tokens require the `REPO_READ` scope to list accessible repositories during [User driven syncing](/docs/features/permission-syncing#how-it-works).

# Manually refreshing permissions

If a user's permissions have changed and they need access updated immediately (without waiting for the next scheduled sync), they can trigger a manual refresh from the **Linked Accounts** page:

1. Navigate to **Settings → Linked Accounts**.
2. Click the **Connected** button next to the relevant code host account.
3. Select **Refresh Permissions** from the dropdown.

<Frame>
<img src="/images/linked_accounts_refresh_permissions.png" alt="Linked Accounts - Refresh Permissions" />
</Frame>

The button will show a spinner while the sync is in progress and display a confirmation once it completes.


# Overriding enforcement per connection

Each [connection](/docs/connections/overview) supports an `enforcePermissions` flag that controls whether permissions are enforced for repositories in that connection. This lets you mix code hosts in a single deployment - for example, enforcing access control on a private GitHub connection while keeping an internal Gerrit instance open to all users.

By default, `enforcePermissions` inherits the value of `PERMISSION_SYNC_ENABLED`. You can override it per connection in the [config file](/docs/configuration/config-file):

```json
{
"connections": {
"my-github": {
"type": "github",
"enforcePermissions": true
},
"my-gerrit": {
"type": "gerrit",
"url": "https://gerrit.example.com",
"enforcePermissions": false
}
}
}
```

Setting `enforcePermissions: false` on a connection makes all repositories from that connection accessible to any user, regardless of the global `PERMISSION_SYNC_ENABLED` setting.

The table below shows when permissions are enforced based on the combination of `PERMISSION_SYNC_ENABLED` and `enforcePermissions`:

| `PERMISSION_SYNC_ENABLED` | `enforcePermissions` | Permissions enforced? |
|--------------------------|---------------------|-----------------------|
| `true` | `true` | Yes |
| `true` | `false` | No |
| `false` | `true` | No |
| `false` | `false` | No |
Comment thread
brendan-kellam marked this conversation as resolved.

# How it works

Permission syncing works by periodically syncing ACLs from the code host(s) to Sourcebot to build an internal mapping between Users and Repositories. This mapping is hydrated in two directions:
Expand All@@ -146,19 +194,5 @@ The sync intervals can be configured using the following settings in the [config

| Setting | Type | Default | Minimum |
|-------------------------------------------------|---------|------------|---------|
| `experiment_repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |
| `experiment_userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |

## Manually refreshing permissions

If a user's permissions have changed and they need access updated immediately (without waiting for the next scheduled sync), they can trigger a manual refresh from the **Linked Accounts** page:

1. Navigate to **Settings → Linked Accounts**.
2. Click the **Connected** button next to the relevant code host account.
3. Select **Refresh Permissions** from the dropdown.

<Frame>
<img src="/images/linked_accounts_refresh_permissions.png" alt="Linked Accounts - Refresh Permissions" />
</Frame>

The button will show a spinner while the sync is in progress and display a confirmation once it completes.
| `repoDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |
| `userDrivenPermissionSyncIntervalMs` | number | 24 hours | 1 |
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/azuredevops.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -189,6 +189,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/bitbucket.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -162,6 +162,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
28 changes: 28 additions & 0 deletions docs/snippets/schemas/v3/connection.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -205,6 +205,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -407,6 +411,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -562,6 +570,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -669,6 +681,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -839,6 +855,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -1047,6 +1067,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand DownExpand Up@@ -1116,6 +1140,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/genericGitHost.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -60,6 +60,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/gerrit.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -100,6 +100,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/gitea.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -148,6 +148,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/github.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -201,6 +201,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/snippets/schemas/v3/gitlab.schema.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -195,6 +195,10 @@
}
},
"additionalProperties": false
},
"enforcePermissions": {
"type": "boolean",
"description": "Controls whether repository permissions are enforced for this connection. When `PERMISSION_SYNC_ENABLED` is false, this setting has no effect. Defaults to the value of `PERMISSION_SYNC_ENABLED`. See https://docs.sourcebot.dev/docs/features/permission-syncing"
}
},
"required": [
Expand Down
Loading