From 569ca6b411fbe7e0db23273a4d32cddcb0764eb3 Mon Sep 17 00:00:00 2001 From: Vorflux AI <249966464+vorflux[bot]@users.noreply.github.com> Date: Mon, 26 Oct 2026 19:18:32 +0000 Subject: [PATCH 1/8] docs(connectors): document source permission enforcement (PRO-3222 PRO-3223) Signed-off-by: Vorflux AI <249966464+vorflux[bot]@users.noreply.github.com> --- .../v2/endpoint/connectors-overview.mdx | 10 +- .../v2/endpoint/create-connector.mdx | 4 +- api-reference/v2/endpoint/fetch-content.mdx | 2 +- .../v2/endpoint/list-connector-providers.mdx | 4 + api-reference/v2/endpoint/list-documents.mdx | 2 +- api-reference/v2/endpoint/query.mdx | 4 +- .../v2/endpoint/source-relations.mdx | 2 +- api-reference/v2/endpoint/subgraph.mdx | 2 +- .../v2/endpoint/update-connector.mdx | 21 ++- api-reference/v2/openapi.json | 120 ++++++++++++++++-- essentials/v2/access-control.mdx | 18 +-- essentials/v2/connectors.mdx | 36 +++++- essentials/v2/query.mdx | 2 +- 13 files changed, 188 insertions(+), 39 deletions(-) diff --git a/api-reference/v2/endpoint/connectors-overview.mdx b/api-reference/v2/endpoint/connectors-overview.mdx index 55a3d022..d7b5ef6d 100644 --- a/api-reference/v2/endpoint/connectors-overview.mdx +++ b/api-reference/v2/endpoint/connectors-overview.mdx @@ -25,7 +25,7 @@ Check on it: Change it: -- [Update Connector](/api-reference/v2/endpoint/update-connector): `PATCH /connectors/{id}` changes the sync interval, connector-level instructions or credentials. +- [Update Connector](/api-reference/v2/endpoint/update-connector): `PATCH /connectors/{id}` changes the sync interval, connector-level instructions, credentials or the owner-only source-permission enforcement setting. - [Update Connector Resource](/api-reference/v2/endpoint/update-connector-resource): `PATCH /connectors/{id}/resources/{resource_id}` changes one resource's instructions or access rule. - [Add Connector Resource](/api-reference/v2/endpoint/add-connector-resource): `POST /connectors/{id}/resources` adds one new resource. - [Delete Connector Resource](/api-reference/v2/endpoint/delete-connector-resource): `DELETE /connectors/{id}/resources/{resource_id}` stops syncing a resource. @@ -37,7 +37,7 @@ Change it: 2. `GET /connectors/{id}/discover` to see which resources are available. 3. `POST /connectors/{id}/configure` with the resources to sync. This starts the first sync. 4. `GET /connectors/{id}/status` until `status` is `healthy` and `lifecycle` is `active`. -5. `POST /query` to search the database and collection chosen during configuration. For restricted content, send the caller’s identity as `acl`; omitting it leaves results unfiltered. `query_apps` is enabled by default. +5. `POST /query` to search the database and collection chosen during configuration. For content from connectors without source-permission enforcement, send the caller's identity as `acl`; omitting it leaves those results unfiltered. Enforced connectors use the authenticated caller instead. `query_apps` is enabled by default. After that, syncs run every `sync_interval_seconds` (one hour by default). Call `POST /connectors/{id}/sync` only when you need data sooner. @@ -46,7 +46,7 @@ After that, syncs run every `sync_interval_seconds` (one hour by default). Call To change a resource that is already configured, use `PATCH /connectors/{id}/resources/{resource_id}` or `POST /connectors/{id}/configure`. `POST /connectors/{id}/resources` adds new resources only: on an existing `resource_id` it returns `409` and changes nothing. - Instructions or access rule on one resource: `PATCH /connectors/{id}/resources/{resource_id}`. Only the fields you send change. -- Instructions, sync interval or credentials for the whole connector: `PATCH /connectors/{id}`. Only the fields you send change. +- Instructions, sync interval, credentials or source-permission enforcement for the whole connector: `PATCH /connectors/{id}`. Only the fields you send change. Only a workspace owner in a signed-in dashboard session can set `follow_source_permissions`; API keys cannot change it. - Name, type, database, collection or metadata of resources: `POST /connectors/{id}/configure`. Resources you leave out of the list are not touched. For each resource you list, send `name` and `resource_type` every time, because omitted values are cleared. Its sync position, instructions and access rule are kept. - A brand new resource: `POST /connectors/{id}/configure` or `POST /connectors/{id}/resources`. @@ -54,13 +54,15 @@ In paths, `{resource_id}` is the resource's id as returned by the Discover and L ## Authentication -All connector endpoints use your HydraDB API key: +Connector API requests use your HydraDB API key: ```http Authorization: Bearer $HYDRA_DB_API_KEY API-Version: 2 ``` +To set `follow_source_permissions`, use a workspace owner's signed-in dashboard session instead; API-key-authenticated requests cannot set it. + ## Key concepts - **Connector:** an authenticated connection to one external provider account. It owns every resource synced from that account. diff --git a/api-reference/v2/endpoint/create-connector.mdx b/api-reference/v2/endpoint/create-connector.mdx index be5ec350..3c171f3a 100644 --- a/api-reference/v2/endpoint/create-connector.mdx +++ b/api-reference/v2/endpoint/create-connector.mdx @@ -12,6 +12,7 @@ Optional settings you can also pass here, and change later with [Update Connecto - `custom_instructions`: guidance for how this connector's documents are interpreted and indexed. See [Custom Ingestion Instructions](/essentials/v2/connectors#custom-ingestion-instructions). - `sync_interval_seconds`: how often scheduled syncs run. Omit it for the provider default (one hour for most providers). +- `follow_source_permissions`: whether content reads always enforce the authenticated caller's source permissions for this connector. It defaults to `false` when omitted. Only a workspace owner in a signed-in dashboard session can set it, and `true` requires the provider to report `rbac_support: true`. API-key-authenticated requests must omit this field. An owner can enable or change it later with [Update Connector](/api-reference/v2/endpoint/update-connector) or in the dashboard. See [Permissions on synced content](/essentials/v2/connectors#enforce-source-permissions-as-the-caller) for how caller identity and request `acl` behave. @@ -70,6 +71,7 @@ curl -X POST 'https://api.hydradb.com/connectors' \ "provider_account_scope": "T12345ACME", "lifecycle": "pending_setup", "sync_status": "idle", + "follow_source_permissions": false, "sync_interval_seconds": 3600, "next_sync_at": "2026-06-01T12:05:00Z", "first_sync_at": "2026-06-01T12:05:00Z", @@ -83,7 +85,7 @@ curl -X POST 'https://api.hydradb.com/connectors' \ - `400`: `provider` or `database` is missing, the provider is unknown, or a setting such as `sync_interval_seconds` is out of range. - `402`: your plan's connector limit is reached. -- `403`: the provider is not available to your organization. +- `403`: the provider is not available to your organization, or the request tries to set `follow_source_permissions` without a workspace owner's signed-in dashboard session. - `422`: `credentials` does not match the provider's `credential_schema`.
diff --git a/api-reference/v2/endpoint/fetch-content.mdx b/api-reference/v2/endpoint/fetch-content.mdx index 8ae108a8..f1453712 100644 --- a/api-reference/v2/endpoint/fetch-content.mdx +++ b/api-reference/v2/endpoint/fetch-content.mdx @@ -49,7 +49,7 @@ curl -G 'https://api.hydradb.com/context/inspect' \ | | Collection scope. If omitted, the default collection is used. | | | What to return. See [Fetch modes](#fetch-modes). (default=`"both"`) | | | TTL of the presigned URL (when `mode` includes `url`). Range `60` to `604800` (7 days). (default=`3600`) | -| | Principals to answer as (document ACLs). A source they cannot see returns the same `404` as a missing one. Repeated (`acl=a&acl=b`) or comma-separated. Omit for no ACL scoping. See [Access Control](/essentials/v2/access-control). | +| | Principals to answer as for content from connectors without source-permission enforcement. A source they cannot see returns the same `404` as a missing one. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values; if `acl` is overridden, the response includes one `meta.warnings` entry with code `acl_overridden_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control). | ## Fetch modes diff --git a/api-reference/v2/endpoint/list-connector-providers.mdx b/api-reference/v2/endpoint/list-connector-providers.mdx index 6db3ea21..526c6a9a 100644 --- a/api-reference/v2/endpoint/list-connector-providers.mdx +++ b/api-reference/v2/endpoint/list-connector-providers.mdx @@ -53,6 +53,8 @@ TypeScript SDK 2.1.7 requires the explicit authorization header for this method. "supported": true, "moveit_support": false, "webhook_support": false, + "rbac_support": true, + "rbac_description": "Captures channel-level access: public channels are visible to the whole workspace, private channels only to their members." "is_alpha": false, "is_beta": false, "rank": 1 @@ -94,6 +96,8 @@ TypeScript SDK 2.1.7 requires the explicit authorization header for this method. Only providers you can connect are listed, so `supported` is always `true`. `webhook_support` is `true` for providers whose data arrives by webhook instead of scheduled syncs. `rank` is `null` for providers without a display position; they are listed last, alphabetically. +`rbac_support` indicates whether the provider captures source permissions as document access rules. When it is `true`, `rbac_description` summarizes the captured permissions. `follow_source_permissions` can only be enabled for a connector when its provider reports `rbac_support: true`; see [Permissions on synced content](/essentials/v2/connectors#enforce-source-permissions-as-the-caller). + ## One provider - `credential_schema` is the JSON Schema for `credentials` on [Create Connector](/api-reference/v2/endpoint/create-connector) and [Update Connector](/api-reference/v2/endpoint/update-connector). It is omitted when unavailable. diff --git a/api-reference/v2/endpoint/list-documents.mdx b/api-reference/v2/endpoint/list-documents.mdx index 5cbf3447..80ac4322 100644 --- a/api-reference/v2/endpoint/list-documents.mdx +++ b/api-reference/v2/endpoint/list-documents.mdx @@ -76,7 +76,7 @@ curl -X POST 'https://api.hydradb.com/context/list' \ | | Items per page, from `1` to `100`. (default=`50`) | | | Structured exact-match filters. See [Filters](#filters). (default=`null`) | | | Field projection. Only the listed fields plus `id`, `database`, `collection` are populated. Only applies to `type=knowledge`. (default=`null`, all fields) | -| | Principals to list as (document ACLs). Only knowledge sources those principals may see come back. Omitted, `[]`, or `["*"]` lists everything. Ignored for `type=memory`. See [Access Control](/essentials/v2/access-control). | +| | Principals to list as for knowledge from connectors without source-permission enforcement. Enforced connector content uses the authenticated caller instead. If supplied `acl` is overridden, the response includes one `meta.warnings` entry with code `acl_overridden_by_connector_enforcement`. Omitted, `[]`, or `["*"]` disables caller-supplied filtering for non-enforced connectors. Ignored for `type=memory`. See [Access Control](/essentials/v2/access-control). | ### Filters diff --git a/api-reference/v2/endpoint/query.mdx b/api-reference/v2/endpoint/query.mdx index 705b5705..7f01b120 100644 --- a/api-reference/v2/endpoint/query.mdx +++ b/api-reference/v2/endpoint/query.mdx @@ -316,7 +316,7 @@ result = client.query( | | Multi-collection scope. Send a list of collection IDs for equal weighting, or an object mapping collection ID to a positive relative weight (at most one decimal place, e.g. `{"finance": 1.5, "legal": 0.8}`) to bias ranking. Up to 100 collections. Do not combine with `collection`. | | | Query terms or natural-language question. Cannot be empty. Maximum 5,000 words. | | | Exact source titles, matched case-insensitively. Matches any listed title, then intersects with `ids` if both are sent. | -| | Caller identities used to enforce document permissions. Omitting `acl`, sending `[]`, or sending `["*"]` disables permission filtering. See [Access Control](/essentials/v2/access-control). | +| | Caller identities used to filter content from connectors without source-permission enforcement. For enforced connectors, HydraDB uses the authenticated caller instead and ignores this field for their content. If you send `acl` while enforcement is enabled, a successful response includes one `meta.warnings` entry with code `acl_overridden_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control) and [Permissions on synced content](/essentials/v2/connectors#enforce-source-permissions-as-the-caller). | | | Omit for the result object with `llm_prompt`. `"structured"` leaves out the prompt string. `"markdown"` returns the prompt string directly as `data`. | | | What to query. `"all"` runs knowledge and memory in parallel over the same scope and merges by `relevancy_score`. (default=`"knowledge"`) | | | Retrieval method. See [Query methods](#decision-matrix). (default=`"hybrid"`) | @@ -348,7 +348,7 @@ Metadata filters work like SQL `WHERE` clauses. Top-level `metadata_filters` key } ``` -See [Metadata and Filters](/essentials/v2/metadata#3-filter-operators) for operators and examples. Filters narrow results. They do not replace the caller's `acl`. +See [Metadata and Filters](/essentials/v2/metadata#3-filter-operators) for operators and examples. Filters narrow results. They do not replace the caller's `acl` or connector-enforced source permissions. ### Decision matrix diff --git a/api-reference/v2/endpoint/source-relations.mdx b/api-reference/v2/endpoint/source-relations.mdx index 5cec5268..2ce36e37 100644 --- a/api-reference/v2/endpoint/source-relations.mdx +++ b/api-reference/v2/endpoint/source-relations.mdx @@ -49,7 +49,7 @@ curl -G 'https://api.hydradb.com/context/relations' \ | | Collection scope. If omitted, the default collection is used. | | | Maximum relation groups to return. Range `1` to `10000`. (default=`5000`) | | | Opaque pagination cursor from a previous response's `next_cursor`. (default=`null`) | -| | Principals to answer as (document ACLs). Only relations from sources those principals may see are returned. Repeated (`acl=a&acl=b`) or comma-separated. Omit for no ACL scoping. See [Access Control](/essentials/v2/access-control). | +| | Principals to answer as for content from connectors without source-permission enforcement. Only relations from sources those principals may see are returned. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values; if `acl` is overridden, the response includes one `meta.warnings` entry with code `acl_overridden_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control). | diff --git a/api-reference/v2/endpoint/subgraph.mdx b/api-reference/v2/endpoint/subgraph.mdx index a8ff92ad..a2e53df0 100644 --- a/api-reference/v2/endpoint/subgraph.mdx +++ b/api-reference/v2/endpoint/subgraph.mdx @@ -56,7 +56,7 @@ curl -G 'https://api.hydradb.com/context/slack_C0BE77_1788320073/subgraph' \ | | Which graph the `id` belongs to. The two graphs are completely separate. (default=`"knowledge"`) | | | Maximum traversal depth in hops. Range `1` to `10`. (default=`5`) | | | Maximum number of members returned. Range `1` to `1000`. When this clips the traversal, `is_truncated` is `true`. (default=`200`) | -| | Principals to answer as (document ACLs). The subgraph then contains only items those principals may see, filtered at every hop. Repeated (`acl=a&acl=b`) or comma-separated. Omit for no ACL scoping. | +| | Principals to answer as for content from connectors without source-permission enforcement. The subgraph then contains only items those principals may see, filtered at every hop. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values; if `acl` is overridden, the response includes one `meta.warnings` entry with code `acl_overridden_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control). | ## How items connect diff --git a/api-reference/v2/endpoint/update-connector.mdx b/api-reference/v2/endpoint/update-connector.mdx index 2f70ca1e..88c34ca1 100644 --- a/api-reference/v2/endpoint/update-connector.mdx +++ b/api-reference/v2/endpoint/update-connector.mdx @@ -4,7 +4,7 @@ description: "Change a connector's instructions, sync interval or credentials in openapi: "api-reference/v2/openapi.json PATCH /connectors/{id}" --- -Update a connector's instructions, sync interval, or credentials. Omitted fields keep their existing values. +Update a connector's instructions, sync interval, credentials, or source-permission enforcement. Omitted fields keep their existing values. - HydraDB validates every field before saving. Invalid input changes nothing. - Credentials are saved before other settings. If a server error occurs afterward, only the credentials may have changed. Retrying the same request is safe. @@ -12,8 +12,19 @@ Update a connector's instructions, sync interval, or credentials. Omitted fields - `custom_instructions` applies to resources without their own instructions. Maximum 4,000 characters. Send `""` to clear it. Changes affect future syncs. See [Custom Ingestion Instructions](/essentials/v2/connectors#custom-ingestion-instructions). - `sync_interval_seconds` reschedules the next sync. Stay within the returned `min_sync_interval_seconds` and `max_sync_interval_seconds`, or send `0` for the provider default. - `credentials` reconnects the existing connector. Send the provider's complete credential set. Resources and saved sync positions are preserved. +- `follow_source_permissions` enables or disables caller-bound enforcement of this connector's captured source permissions. Send `true` to enforce them on every content read, or `false` to return to opt-in request `acl` filtering. Omit it to keep the current value. Only a workspace owner in a signed-in dashboard session can set it; `true` requires the provider to report `rbac_support: true`. API-key-authenticated requests cannot set it. See [Permissions on synced content](/essentials/v2/connectors#enforce-source-permissions-as-the-caller) and [Access Control](/essentials/v2/access-control). -Only these three fields can be updated. A connector's `name`, `database`, `collection` and `provider_account_scope` cannot be changed after creation. Omit them from the request; unsupported fields can cause a `400` response. +To enable enforcement later, send this field in a separate PATCH request, or use **Follow source permissions** in the dashboard's connector settings: + +```json +{ + "follow_source_permissions": true +} +``` + +Do not combine `follow_source_permissions` and `credentials` in the same PATCH request. Send them in separate requests. + +Only `custom_instructions`, `sync_interval_seconds`, `credentials`, and `follow_source_permissions` can be updated. A connector's `name`, `database`, `collection` and `provider_account_scope` cannot be changed after creation. Omit them from the request; unsupported fields can cause a `400` response. @@ -57,6 +68,7 @@ curl -X PATCH 'https://api.hydradb.com/connectors/{id}' \ { "connector_id": "{connector_id}", "sync_interval_seconds": 3600, + "follow_source_permissions": false, "next_sync_at": "2026-06-01T13:00:00Z", "min_sync_interval_seconds": 300, "max_sync_interval_seconds": 604800, @@ -70,9 +82,12 @@ curl -X PATCH 'https://api.hydradb.com/connectors/{id}' \ ## Errors -- `400`: the request includes an unsupported field, `custom_instructions` is over 4,000 characters, or `sync_interval_seconds` is outside the provider's range. Nothing is changed. +- `400`: the request includes an unsupported field, `follow_source_permissions` is combined with `credentials`, the provider does not report `rbac_support` for `follow_source_permissions: true`, `custom_instructions` is over 4,000 characters, or `sync_interval_seconds` is outside the provider's range. Nothing is changed. +- `403`: the request tries to set `follow_source_permissions` without a workspace owner's signed-in dashboard session. - `404`: no connector with this id in your organization. +- `409`: another update changed the permission setting at the same time. Reload the connector and retry. - `422`: `credentials` does not match the provider's `credential_schema`. +- `503`: the provider capability catalog is unavailable. Retry the request.
diff --git a/api-reference/v2/openapi.json b/api-reference/v2/openapi.json index f9156676..b755e66a 100644 --- a/api-reference/v2/openapi.json +++ b/api-reference/v2/openapi.json @@ -2905,6 +2905,20 @@ "title": "HandlerErrorResponse", "type": "object" }, + "handler.ResponseWarning": { + "properties": { + "code": { + "description": "Code identifies the warning type, such as acl_overridden_by_connector_enforcement.", + "type": "string" + }, + "message": { + "description": "Human-readable explanation of the warning.", + "example": "The caller-supplied acl was ignored for content from connectors that enforce source permissions.", + "type": "string" + } + }, + "type": "object" + }, "handler.apiError": { "properties": { "code": { @@ -2966,11 +2980,11 @@ ] }, "rbac_description": { - "description": "One-line summary of which provider permissions are captured as document access rules. Not returned by this endpoint.", + "description": "One-line summary of the provider permissions captured as document access rules. Present when `rbac_support` is true.", "type": "string" }, "rbac_support": { - "description": "Reserved. Always `false` on this endpoint.", + "description": "True when the provider captures source permissions as document access rules. Connector source-permission enforcement can be enabled only when this is true.", "example": true, "type": "boolean" }, @@ -3146,6 +3160,11 @@ "description": "RFC3339 timestamp of the first sync that sent at least one object for ingestion. Empty until then.", "type": "string" }, + "follow_source_permissions": { + "description": "Whether source permissions are enforced. False when unsupported. When true, reads use the authenticated caller; otherwise request `acl` remains an opt-in filter.", + "example": true, + "type": "boolean" + }, "last_attempted_sync_at": { "description": "RFC3339 timestamp of the most recent sync attempt (successful or not).", "example": "2026-07-02T17:00:00Z", @@ -3288,6 +3307,11 @@ "example": "acme_corp", "type": "string" }, + "follow_source_permissions": { + "description": "Optional owner-only setting; defaults to false. True requires provider `rbac_support` and enables caller-bound reads; false keeps request `acl` as an opt-in filter.", + "example": true, + "type": "boolean" + }, "name": { "description": "Human-readable label for this connector.", "example": "general", @@ -3373,6 +3397,11 @@ "description": "RFC3339 timestamp when the first scheduled sync runs.", "type": "string" }, + "follow_source_permissions": { + "description": "Whether source permissions are enforced. False when unsupported. When true, reads use the authenticated caller; otherwise request `acl` remains an opt-in filter.", + "example": true, + "type": "boolean" + }, "last_attempted_sync_at": { "description": "RFC3339 timestamp of the most recent sync attempt (successful or not).", "example": "2026-07-02T17:00:00Z", @@ -3889,6 +3918,11 @@ "description": "Ingestion and indexing instructions for every resource on this connector that has no instructions of its own. Omit to leave unchanged; `\"\"` clears. Up to 4000 characters, applied from the next sync.", "type": "string" }, + "follow_source_permissions": { + "description": "Set whether the connector follows source permissions. Omit to keep the current value; only a workspace owner may set it. True requires provider catalog `rbac_support`.", + "example": true, + "type": "boolean" + }, "sync_interval_seconds": { "description": "How frequently the scheduler triggers incremental syncs, in seconds. Bounded per provider; send 0 or omit to use the provider default. Change it later with PATCH /connectors/{id}.", "example": 3600, @@ -3915,6 +3949,11 @@ "example": true, "type": "boolean" }, + "follow_source_permissions": { + "description": "Whether source permissions are enforced. False when unsupported. When true, reads use the authenticated caller; otherwise request `acl` remains an opt-in filter.", + "example": true, + "type": "boolean" + }, "max_sync_interval_seconds": { "description": "Largest sync_interval_seconds this connector's provider allows.", "example": 604800, @@ -4348,7 +4387,8 @@ "provider": "slack", "rbac_support": true, "supported": true, - "webhook_support": true + "webhook_support": true, + "rbac_description": "Captures channel-level access: public channels are visible to the workspace, private channels only to their members." } ], "items": { @@ -4828,6 +4868,20 @@ "example": "tenant_1234", "type": "string", "x-deprecated": "true" + }, + "warnings": { + "description": "Non-fatal response notices. When request `acl` is overridden for enforced connector content, exactly one warning has code `acl_overridden_by_connector_enforcement`.", + "example": [ + { + "code": "acl_overridden_by_connector_enforcement", + "message": "The caller-supplied acl was ignored for content from connectors that enforce source permissions." + } + ], + "items": { + "$ref": "#/components/schemas/handler.ResponseWarning" + }, + "type": "array", + "uniqueItems": false } }, "title": "HandlerResponseMeta", @@ -5290,7 +5344,7 @@ "list.V2ListContentRequest": { "properties": { "acl": { - "description": "Principals to answer as: only context they may see is listed. Omit it for no access scoping.", + "description": "Principals to answer as. For non-enforced connectors, only context visible to these principals is listed. Enforced connector content uses the authenticated caller instead. If sent and overridden, one `meta.warnings` entry has code `acl_overridden_by_connector_enforcement`.", "items": { "type": "string" }, @@ -6186,7 +6240,7 @@ "search.QueryRequest": { "properties": { "acl": { - "description": "Principals to query as: emails or `user_email:`, `group:` or `domain:` principals. Returns their context plus public and unrestricted context. Omit, `[]` or `[\"*\"]` for no scoping.", + "description": "Principals to query as: emails or `user_email:`, `group:` or `domain:` principals. For non-enforced connectors, returns their context plus public and unrestricted context. Enforced connectors use the authenticated caller instead. If sent and overridden, one `meta.warnings` entry has code `acl_overridden_by_connector_enforcement`. Omit, `[]` or `[\"*\"]` to disable caller-supplied filtering for non-enforced connectors.", "items": { "type": "string" }, @@ -8023,7 +8077,7 @@ "x-fern-sdk-method-name": "list" }, "post": { - "description": "Create a connector for a provider and store its credentials.", + "description": "Create a connector for a provider and store its credentials. `follow_source_permissions` defaults to false when omitted, so writers may create connectors without choosing the setting. Only a workspace owner in a human dashboard session may explicitly set it, and true is accepted only when the provider catalog reports rbac_support. When true, content reads always use the authenticated caller; when false, request `acl` remains an opt-in filter.", "requestBody": { "content": { "application/json": { @@ -8056,6 +8110,16 @@ }, "description": "Bad Request" }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/handler.ErrorResponse" + } + } + }, + "description": "Setting follow_source_permissions requires a workspace owner in a signed-in dashboard session." + }, "500": { "content": { "application/json": { @@ -8092,7 +8156,7 @@ }, "/connectors/providers": { "get": { - "description": "Lists the providers you can connect. With `id`, describes one: its searchable object types and fields (with `filter_key`), `credential_schema`, and `setup_guide` when needed.", + "description": "Lists the providers you can connect, including whether source-permission capture is supported (`rbac_support`) and its summary (`rbac_description`). With `id`, describes one provider: its searchable object types and fields (with `filter_key`), `credential_schema`, and `setup_guide` when needed.", "parameters": [ { "description": "Provider name (e.g. slack, gmail). Omit to list all.", @@ -8265,7 +8329,7 @@ "x-fern-sdk-method-name": "get" }, "patch": { - "description": "Update the supplied connector settings. Use `credentials` to reconnect, `sync_interval_seconds` to change cadence, or `custom_instructions` to change ingestion instructions.", + "description": "Update the supplied connector settings. Use `credentials` to reconnect, `sync_interval_seconds` to change cadence, `custom_instructions` to change ingestion instructions, or `follow_source_permissions` to set the owner-only enforcement mode. True requires provider catalog `rbac_support`; when enabled, content reads use the authenticated caller, while false keeps request `acl` as an opt-in filter.", "parameters": [ { "description": "Connector ID", @@ -8310,6 +8374,16 @@ }, "description": "Bad Request" }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/handler.ErrorResponse" + } + } + }, + "description": "Setting follow_source_permissions requires a workspace owner in a signed-in dashboard session." + }, "404": { "content": { "application/json": { @@ -8320,6 +8394,16 @@ }, "description": "Not Found" }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/handler.ErrorResponse" + } + } + }, + "description": "The source-permissions revision changed after the connector was loaded; reload and retry. If the connector was deleted, the handler returns 404." + }, "500": { "content": { "application/json": { @@ -8329,6 +8413,16 @@ } }, "description": "Internal Server Error" + }, + "503": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/handler.ErrorResponse" + } + } + }, + "description": "The provider capability catalog is unavailable; retry the request." } }, "security": [ @@ -9470,7 +9564,7 @@ } }, { - "description": "Principals to answer as. The context must be visible to them, or the response is `404`. Repeated (`acl=a\u0026acl=b`) or comma-separated. Omit it for no access scoping.", + "description": "Principals to inspect as. For non-enforced connector content, only contexts visible to these principals can be inspected; a context that is not visible returns `404`. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values. If sent and overridden, one `meta.warnings` entry has code `acl_overridden_by_connector_enforcement`.", "in": "query", "name": "acl", "schema": { @@ -9662,7 +9756,7 @@ } }, { - "description": "Principals to answer as; only results they may see are returned. Repeat the parameter or send a comma-separated list. Omit it for no scoping.", + "description": "Principals to answer as. For non-enforced connector content, only results visible to these principals are returned. Enforced connector content uses the authenticated caller instead. Repeat the parameter or send a comma-separated list. If sent and overridden, one `meta.warnings` entry has code `acl_overridden_by_connector_enforcement`.", "in": "query", "name": "acl", "schema": { @@ -9908,7 +10002,7 @@ } }, { - "description": "Principals to answer as; only contexts they may see are returned, checked at every hop. Omit for no access scoping. Repeat or comma-separate.", + "description": "Principals to answer as. For non-enforced connector content, only contexts visible to these principals are returned, checked at every hop. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values. If sent and overridden, one `meta.warnings` entry has code `acl_overridden_by_connector_enforcement`.", "in": "query", "name": "acl", "schema": { @@ -10127,7 +10221,7 @@ } }, { - "description": "Principals allowed to read the returned contexts. Omit for no additional scoping.", + "description": "Principals allowed to read the returned contexts. For non-enforced connector content, only contexts visible to these principals are returned. Enforced connector content uses the authenticated caller instead for every returned context. If sent and overridden, one `meta.warnings` entry has code `acl_overridden_by_connector_enforcement`.", "in": "query", "name": "acl", "schema": { @@ -11351,4 +11445,4 @@ "x-fern-default": "2" } ] -} \ No newline at end of file +} diff --git a/essentials/v2/access-control.mdx b/essentials/v2/access-control.mdx index 3113ee70..1d066d85 100644 --- a/essentials/v2/access-control.mdx +++ b/essentials/v2/access-control.mdx @@ -183,7 +183,7 @@ Access control works alongside [metadata filters](/essentials/v2/metadata): filt `POST /context/list` takes the same `acl` field with the same meaning. The `GET /context/chunks`, `GET /context/relations`, and `GET /context/subgraph` endpoints take it as a query parameter, repeated (`acl=a&acl=b`) or comma-separated. -Access control is opt-in per request. A query without an `acl` field is not filtered and returns everything in scope. Adding ACLs to your documents changes nothing until your queries declare who is asking. +For content from connectors without source-permission enforcement, access control is opt-in per request. A query without an `acl` field is not filtered by caller identity. For content from a connector with `follow_source_permissions` enabled, HydraDB enforces the authenticated caller's source permissions on every read instead. See [Permissions on synced content](/essentials/v2/connectors#enforce-source-permissions-as-the-caller) for how to enable it and how caller identities are selected. ## 2. Principals @@ -206,12 +206,12 @@ Principals are lowercased, trimmed, and deduplicated on the way in. `__public__` | You send | Behavior | |---|---| -| No `acl` field | No filtering. | +| No `acl` field | No caller-supplied ACL filtering. Connectors with source-permission enforcement still apply the authenticated caller's permissions. | | `"acl": []` | Same as omitting it. On a query, an empty list does not mean nobody. | -| `"acl": ["*"]` | Same as omitting it. An explicit "search as an administrator". | -| `"acl": ["grace@acme.com"]` | Filtered to what Grace may see: her own documents, anything shared with `domain:acme.com`, public documents, and unrestricted documents. | -| `"acl": ["grace@acme.com", "group:slack:C0123"]` | Grace's view plus everything shared with that group. Group membership is never derived from an email; declare it. | -| `"acl": ["__private__"]` | Public and unrestricted documents only. | +| `"acl": ["*"]` | Same as omitting it. An explicit "search as an administrator" for content without connector enforcement. | +| `"acl": ["grace@acme.com"]` | Filtered to what Grace may see on content without connector enforcement: her own documents, anything shared with `domain:acme.com`, public documents, and unrestricted documents. | +| `"acl": ["grace@acme.com", "group:slack:C0123"]` | Grace's view plus everything shared with that group on content without connector enforcement. Group membership is never derived from an email; declare it. | +| `"acl": ["__private__"]` | Public and unrestricted documents only on content without connector enforcement. | Several emails in one list see the union of their views. An entry that is neither an email nor a recognized principal is kept as-is and matches nothing but public and unrestricted documents. A typo narrows results; it never widens them. If a caller sees less than you expect, check the principal spelling first. @@ -227,7 +227,9 @@ For supported providers, HydraDB reads the source app's own permissions on every | **Confluence** | Space-level view permissions, with groups expanded to member emails, plus per-page view restrictions. | | **Jira** | Who holds Browse access per project, plus per-issue security levels. | -Capture is also built for GitLab, Linear, Dropbox, Zendesk, PagerDuty, Typeform, Attio, LaunchDarkly, ServiceNow, Microsoft Teams, and Outlook, and is switched on per provider. The provider catalog does not yet flag which providers capture permissions, so treat this list as the current set, and check [Get Connector Status](/api-reference/v2/endpoint/get-connector-status) for an `acl_warning` after the first sync. For any other provider, [set your own rule on the resource](#set-your-own-rule-on-a-resource). +Capture is also built for GitLab, Linear, Dropbox, Zendesk, PagerDuty, Typeform, Attio, LaunchDarkly, ServiceNow, Microsoft Teams, and Outlook, and is switched on per provider. The [provider catalog](/api-reference/v2/endpoint/list-connector-providers) reports capture support in `rbac_support` and summarizes it in `rbac_description`. Check [Get Connector Status](/api-reference/v2/endpoint/get-connector-status) for an `acl_warning` after the first sync. For any other provider, [set your own rule on the resource](#set-your-own-rule-on-a-resource). + +By default, captured permissions are not enforced automatically on reads. A workspace owner can enable per-connector enforcement with `follow_source_permissions`, which is available only when the provider supports `rbac_support`. With enforcement enabled, the authenticated caller replaces a request's `acl` for content from that connector; an `acl` supplied on the request still scopes content from non-enforced connectors. See [Permissions on synced content](/essentials/v2/connectors#enforce-source-permissions-as-the-caller) for the identity rules and the machine-readable warning returned when an `acl` is overridden. ### Set your own rule on a resource @@ -366,7 +368,7 @@ Check the principal forms on both sides. `group:slack:C0123` on the document onl ## Related -- [Connectors](/essentials/v2/connectors): syncing app data, and per-resource ACL rules +- [Connectors](/essentials/v2/connectors): syncing app data, per-resource ACL rules, and caller-bound source-permission enforcement - [App Sources](/essentials/v2/app-sources): the ingest shape that carries `acl` - [Query](/essentials/v2/query): the `acl` field alongside every other retrieval parameter - [Metadata and Filters](/essentials/v2/metadata): narrow results by metadata diff --git a/essentials/v2/connectors.mdx b/essentials/v2/connectors.mdx index ad8ece0e..4bf90f51 100644 --- a/essentials/v2/connectors.mdx +++ b/essentials/v2/connectors.mdx @@ -14,7 +14,7 @@ In this guide: 3. [Change a connector after setup](#3-change-a-connector-after-setup): which call changes what. 4. [Custom ingestion instructions](#4-custom-ingestion-instructions): tell a connector how to read its documents. 5. [Filter on what HydraDB writes](#5-filter-on-what-hydradb-writes): the metadata every synced object carries. -6. [Permissions on synced content](#6-permissions-on-synced-content): the source app's permissions, and your own rules. +6. [Permissions on synced content](#6-permissions-on-synced-content): the source app's permissions, your own rules, and optional caller-bound enforcement. 7. [Connect several accounts of one provider](#7-connect-several-accounts-of-one-provider). 8. [Common mistakes](#common-mistakes) and [related pages](#related). @@ -277,6 +277,7 @@ curl -X POST 'https://api.hydradb.com/connectors/{id}/configure' \ | `credentials` | create | The provider's credentials, in the shape of its `credential_schema`. Credentials that do not match the schema are rejected with `422`. | | `custom_instructions` | create, configure | Guidance for how synced documents are interpreted, for the whole connector or for one resource. See [section 4](#4-custom-ingestion-instructions). | | `sync_interval_seconds` | create | How often scheduled syncs run. Omit it for the provider default, one hour for most providers. | +| `follow_source_permissions` | create, update | Whether reads from this connector always enforce the authenticated caller's source permissions. Optional and `false` by default. Only a workspace owner can set it, and enabling it requires a provider with `rbac_support`. See [enforced source permissions](#enforce-source-permissions-as-the-caller). | | `lookback_days` | configure | How much history the first sync fetches (default `30`). After that, each sync fetches only what is new. Above 30, some providers fetch the older history in the background and the response reports `backfill: true`. | | `resource_id`, `resource_type`, `name` | configure | The `id`, `resource_type`, and `name` of an entry from discover. Send all three every time you list a resource. | | `metadata` | configure | Fields merged into the database metadata of every object from this resource. Declare the ones you filter on in your database's [metadata schema](/essentials/v2/metadata). | @@ -512,9 +513,38 @@ To see which provider-native fields a connector writes, call [`GET /connectors/p ## 6. Permissions on synced content -For supported providers, HydraDB reads the source app's permissions on every sync and applies them as document access rules, so a query made on someone's behalf cannot surface a private channel, a restricted Drive file, or a repository they cannot see. Slack, Google Drive, GitHub, Confluence, and Jira are among the supported providers; [Access Control](/essentials/v2/access-control) lists what is captured for each. +For supported providers, HydraDB reads the source app's permissions on every sync and applies them as document access rules. Slack, Google Drive, GitHub, Confluence, and Jira are among the supported providers; [Access Control](/essentials/v2/access-control) lists what is captured for each. Capturing source permissions and enforcing them on every read are separate: the connector's `follow_source_permissions` setting controls enforcement. -Send the caller's identity as `acl` on every query. A query without it ignores document permissions. +By default, `follow_source_permissions` is `false`. In this mode, access control remains opt-in on each request: send the caller's identity in `acl` to filter content, and a request without `acl` is not filtered by caller identity. This remains true for content from connectors whose enforcement is disabled, even when the same request also reads enforced connector content. + +### Enforce source permissions as the caller + +Set `follow_source_permissions` to `true` to make reads from this connector use the authenticated caller's identity against the source permissions HydraDB captured. The provider must report `rbac_support: true` in [List Connector Providers](/api-reference/v2/endpoint/list-connector-providers). The setting is optional on [`POST /connectors`](/api-reference/v2/endpoint/create-connector), defaults to `false`, and can be enabled or changed later with [`PATCH /connectors/{id}`](/api-reference/v2/endpoint/update-connector). In the dashboard, an owner can use the **Follow source permissions** control in the connector settings. + +Only a workspace owner can set or change this setting. The API requires an owner in a signed-in dashboard session; API-key-authenticated requests can create a connector with the default `false` value, but cannot choose or change the setting. + +When enforcement is enabled, HydraDB selects the identity from authentication rather than trusting a caller-supplied `acl`: + +- **API key:** the email of the person who created the key. +- **MCP OAuth:** the signed-in user. +- **Dashboard:** the signed-in user. + +If a content-read request includes `acl`, HydraDB ignores it for content from connectors with enforcement enabled. The `acl` still scopes content from non-enforced connectors. A successful response includes exactly one machine-readable warning for the override in `meta.warnings`: + +```json +{ + "meta": { + "warnings": [ + { + "code": "acl_overridden_by_connector_enforcement", + "message": "The caller-supplied acl was ignored for content from connectors that enforce source permissions." + } + ] + } +} +``` + +An API key stays tied to its creator. When a member is removed from the workspace, that member's API keys stop working; another member must use a key created under their own account. Your own rule per resource goes in `acl` at configure time, or afterwards on its own: diff --git a/essentials/v2/query.mdx b/essentials/v2/query.mdx index d1be2b7a..7a40c53f 100644 --- a/essentials/v2/query.mdx +++ b/essentials/v2/query.mdx @@ -223,7 +223,7 @@ Three fields bring in context beyond the passages that matched. All three are on ## 6. Query on behalf of a user -Send the caller's email in `acl`, such as `"acl": ["grace@acme.com"]`, and results are limited to documents that person may retrieve, plus public and unrestricted ones. Without `acl` the query is not filtered, so derive it from your signed-in session, never from the client. [Access Control](/essentials/v2/access-control) covers setting ACLs on documents and the principal forms. +For content from connectors without source-permission enforcement, send the caller's email in `acl`, such as `"acl": ["grace@acme.com"]`, to filter results to documents that person may retrieve, plus public and unrestricted ones. Without `acl`, that content is not filtered by caller identity. For connectors with `follow_source_permissions` enabled, HydraDB uses the authenticated caller instead and ignores a request `acl` for that connector's content. API keys use the key creator's email; MCP OAuth and dashboard requests use the signed-in user. If you send `acl` while enforcement is enabled, a successful response includes one `meta.warnings` entry with code `acl_overridden_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control) and [Permissions on synced content](/essentials/v2/connectors#enforce-source-permissions-as-the-caller) for more. ## Common mistakes From 8759e90a8190b925273a924263febb6c5691950d Mon Sep 17 00:00:00 2001 From: Vorflux AI <249966464+vorflux[bot]@users.noreply.github.com> Date: Mon, 26 Oct 2026 19:23:22 +0000 Subject: [PATCH 2/8] fix(docs): validate permission examples (PRO-3222 PRO-3223) Signed-off-by: Vorflux AI <249966464+vorflux[bot]@users.noreply.github.com> --- api-reference/v2/endpoint/list-connector-providers.mdx | 2 +- api-reference/v2/endpoint/update-connector.mdx | 2 +- api-reference/v2/openapi.json | 1 + essentials/v2/connectors.mdx | 6 +++--- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/api-reference/v2/endpoint/list-connector-providers.mdx b/api-reference/v2/endpoint/list-connector-providers.mdx index 526c6a9a..1986c8b3 100644 --- a/api-reference/v2/endpoint/list-connector-providers.mdx +++ b/api-reference/v2/endpoint/list-connector-providers.mdx @@ -54,7 +54,7 @@ TypeScript SDK 2.1.7 requires the explicit authorization header for this method. "moveit_support": false, "webhook_support": false, "rbac_support": true, - "rbac_description": "Captures channel-level access: public channels are visible to the whole workspace, private channels only to their members." + "rbac_description": "Captures channel-level access: public channels are visible to the whole workspace, private channels only to their members.", "is_alpha": false, "is_beta": false, "rank": 1 diff --git a/api-reference/v2/endpoint/update-connector.mdx b/api-reference/v2/endpoint/update-connector.mdx index 88c34ca1..1039f0a3 100644 --- a/api-reference/v2/endpoint/update-connector.mdx +++ b/api-reference/v2/endpoint/update-connector.mdx @@ -12,7 +12,7 @@ Update a connector's instructions, sync interval, credentials, or source-permiss - `custom_instructions` applies to resources without their own instructions. Maximum 4,000 characters. Send `""` to clear it. Changes affect future syncs. See [Custom Ingestion Instructions](/essentials/v2/connectors#custom-ingestion-instructions). - `sync_interval_seconds` reschedules the next sync. Stay within the returned `min_sync_interval_seconds` and `max_sync_interval_seconds`, or send `0` for the provider default. - `credentials` reconnects the existing connector. Send the provider's complete credential set. Resources and saved sync positions are preserved. -- `follow_source_permissions` enables or disables caller-bound enforcement of this connector's captured source permissions. Send `true` to enforce them on every content read, or `false` to return to opt-in request `acl` filtering. Omit it to keep the current value. Only a workspace owner in a signed-in dashboard session can set it; `true` requires the provider to report `rbac_support: true`. API-key-authenticated requests cannot set it. See [Permissions on synced content](/essentials/v2/connectors#enforce-source-permissions-as-the-caller) and [Access Control](/essentials/v2/access-control). +- `follow_source_permissions` enables or disables caller-bound enforcement of this connector's captured source permissions. Existing connectors remain `false` until an owner enables it. Send `true` to enforce captured permissions on every content read, or `false` to return to opt-in request `acl` filtering. Omit it to keep the current value. The change takes effect on the next content request for already-synced documents and does not require re-ingestion. Only a workspace owner in a signed-in dashboard session can set it; `true` requires the provider to report `rbac_support: true`. API-key-authenticated requests cannot set it. See [Permissions on synced content](/essentials/v2/connectors#enforce-source-permissions-as-the-caller) and [Access Control](/essentials/v2/access-control). To enable enforcement later, send this field in a separate PATCH request, or use **Follow source permissions** in the dashboard's connector settings: diff --git a/api-reference/v2/openapi.json b/api-reference/v2/openapi.json index b755e66a..35924276 100644 --- a/api-reference/v2/openapi.json +++ b/api-reference/v2/openapi.json @@ -2917,6 +2917,7 @@ "type": "string" } }, + "title": "HandlerResponseWarning", "type": "object" }, "handler.apiError": { diff --git a/essentials/v2/connectors.mdx b/essentials/v2/connectors.mdx index 4bf90f51..d641a187 100644 --- a/essentials/v2/connectors.mdx +++ b/essentials/v2/connectors.mdx @@ -515,17 +515,17 @@ To see which provider-native fields a connector writes, call [`GET /connectors/p For supported providers, HydraDB reads the source app's permissions on every sync and applies them as document access rules. Slack, Google Drive, GitHub, Confluence, and Jira are among the supported providers; [Access Control](/essentials/v2/access-control) lists what is captured for each. Capturing source permissions and enforcing them on every read are separate: the connector's `follow_source_permissions` setting controls enforcement. -By default, `follow_source_permissions` is `false`. In this mode, access control remains opt-in on each request: send the caller's identity in `acl` to filter content, and a request without `acl` is not filtered by caller identity. This remains true for content from connectors whose enforcement is disabled, even when the same request also reads enforced connector content. +By default, `follow_source_permissions` is `false`. Omitting it on create leaves the new connector unenforced, and existing connectors remain unenforced until an owner enables the setting. In this mode, access control remains opt-in on each request: send the caller's identity in `acl` to filter content, and a request without `acl` is not filtered by caller identity. This remains true for content from connectors whose enforcement is disabled, even when the same request also reads enforced connector content. MCP OAuth does not enforce caller identity for a non-enforced connector; send `acl` when that request needs caller filtering. ### Enforce source permissions as the caller -Set `follow_source_permissions` to `true` to make reads from this connector use the authenticated caller's identity against the source permissions HydraDB captured. The provider must report `rbac_support: true` in [List Connector Providers](/api-reference/v2/endpoint/list-connector-providers). The setting is optional on [`POST /connectors`](/api-reference/v2/endpoint/create-connector), defaults to `false`, and can be enabled or changed later with [`PATCH /connectors/{id}`](/api-reference/v2/endpoint/update-connector). In the dashboard, an owner can use the **Follow source permissions** control in the connector settings. +Set `follow_source_permissions` to `true` to make reads from this connector use the authenticated caller's identity against the source permissions HydraDB captured. The provider must report `rbac_support: true` in [List Connector Providers](/api-reference/v2/endpoint/list-connector-providers). The setting is optional on [`POST /connectors`](/api-reference/v2/endpoint/create-connector), defaults to `false`, and can be enabled or changed later with [`PATCH /connectors/{id}`](/api-reference/v2/endpoint/update-connector). In the dashboard, an owner can use the **Follow source permissions** control in the connector settings. A change takes effect on the next content request for already-synced documents and does not require re-ingestion. Only a workspace owner can set or change this setting. The API requires an owner in a signed-in dashboard session; API-key-authenticated requests can create a connector with the default `false` value, but cannot choose or change the setting. When enforcement is enabled, HydraDB selects the identity from authentication rather than trusting a caller-supplied `acl`: -- **API key:** the email of the person who created the key. +- **API key or pasted-key MCP:** the email of the person who created the key. - **MCP OAuth:** the signed-in user. - **Dashboard:** the signed-in user. From ce1768baa4ad9df9ae0370a953ab6d593567be79 Mon Sep 17 00:00:00 2001 From: Vorflux AI <249966464+vorflux[bot]@users.noreply.github.com> Date: Mon, 26 Oct 2026 19:31:27 +0000 Subject: [PATCH 3/8] fix(docs): clarify ACL behavior outside enforced connectors (PRO-3223) Signed-off-by: Vorflux AI <249966464+vorflux[bot]@users.noreply.github.com> --- api-reference/v2/endpoint/fetch-content.mdx | 2 +- api-reference/v2/endpoint/list-documents.mdx | 2 +- api-reference/v2/endpoint/query.mdx | 2 +- api-reference/v2/endpoint/source-relations.mdx | 2 +- api-reference/v2/endpoint/subgraph.mdx | 2 +- api-reference/v2/openapi.json | 12 ++++++------ essentials/v2/access-control.mdx | 2 +- essentials/v2/query.mdx | 2 +- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/api-reference/v2/endpoint/fetch-content.mdx b/api-reference/v2/endpoint/fetch-content.mdx index f1453712..fa8a4e32 100644 --- a/api-reference/v2/endpoint/fetch-content.mdx +++ b/api-reference/v2/endpoint/fetch-content.mdx @@ -49,7 +49,7 @@ curl -G 'https://api.hydradb.com/context/inspect' \ | | Collection scope. If omitted, the default collection is used. | | | What to return. See [Fetch modes](#fetch-modes). (default=`"both"`) | | | TTL of the presigned URL (when `mode` includes `url`). Range `60` to `604800` (7 days). (default=`3600`) | -| | Principals to answer as for content from connectors without source-permission enforcement. A source they cannot see returns the same `404` as a missing one. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values; if `acl` is overridden, the response includes one `meta.warnings` entry with code `acl_overridden_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control). | +| | Principals to answer as for directly ingested knowledge and content from connectors without source-permission enforcement. A source they cannot see returns the same `404` as a missing one. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values; if `acl` is overridden, the response includes one `meta.warnings` entry with code `acl_overridden_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control). | ## Fetch modes diff --git a/api-reference/v2/endpoint/list-documents.mdx b/api-reference/v2/endpoint/list-documents.mdx index 80ac4322..0601cf99 100644 --- a/api-reference/v2/endpoint/list-documents.mdx +++ b/api-reference/v2/endpoint/list-documents.mdx @@ -76,7 +76,7 @@ curl -X POST 'https://api.hydradb.com/context/list' \ | | Items per page, from `1` to `100`. (default=`50`) | | | Structured exact-match filters. See [Filters](#filters). (default=`null`) | | | Field projection. Only the listed fields plus `id`, `database`, `collection` are populated. Only applies to `type=knowledge`. (default=`null`, all fields) | -| | Principals to list as for knowledge from connectors without source-permission enforcement. Enforced connector content uses the authenticated caller instead. If supplied `acl` is overridden, the response includes one `meta.warnings` entry with code `acl_overridden_by_connector_enforcement`. Omitted, `[]`, or `["*"]` disables caller-supplied filtering for non-enforced connectors. Ignored for `type=memory`. See [Access Control](/essentials/v2/access-control). | +| | Principals to list as for directly ingested knowledge and knowledge from connectors without source-permission enforcement. Enforced connector content uses the authenticated caller instead. If supplied `acl` is overridden, the response includes one `meta.warnings` entry with code `acl_overridden_by_connector_enforcement`. Omitted, `[]`, or `["*"]` disables caller-supplied filtering outside enforced connectors. Ignored for `type=memory`. See [Access Control](/essentials/v2/access-control). | ### Filters diff --git a/api-reference/v2/endpoint/query.mdx b/api-reference/v2/endpoint/query.mdx index 7f01b120..dd77d3a0 100644 --- a/api-reference/v2/endpoint/query.mdx +++ b/api-reference/v2/endpoint/query.mdx @@ -316,7 +316,7 @@ result = client.query( | | Multi-collection scope. Send a list of collection IDs for equal weighting, or an object mapping collection ID to a positive relative weight (at most one decimal place, e.g. `{"finance": 1.5, "legal": 0.8}`) to bias ranking. Up to 100 collections. Do not combine with `collection`. | | | Query terms or natural-language question. Cannot be empty. Maximum 5,000 words. | | | Exact source titles, matched case-insensitively. Matches any listed title, then intersects with `ids` if both are sent. | -| | Caller identities used to filter content from connectors without source-permission enforcement. For enforced connectors, HydraDB uses the authenticated caller instead and ignores this field for their content. If you send `acl` while enforcement is enabled, a successful response includes one `meta.warnings` entry with code `acl_overridden_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control) and [Permissions on synced content](/essentials/v2/connectors#enforce-source-permissions-as-the-caller). | +| | Caller identities used to filter directly ingested knowledge and content from connectors without source-permission enforcement. Omitting `acl`, sending `[]`, or sending `["*"]` disables this caller-supplied filtering. For enforced connectors, HydraDB uses the authenticated caller instead and ignores this field for their content. If you send `acl` while enforcement is enabled, a successful response includes one `meta.warnings` entry with code `acl_overridden_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control) and [Permissions on synced content](/essentials/v2/connectors#enforce-source-permissions-as-the-caller). | | | Omit for the result object with `llm_prompt`. `"structured"` leaves out the prompt string. `"markdown"` returns the prompt string directly as `data`. | | | What to query. `"all"` runs knowledge and memory in parallel over the same scope and merges by `relevancy_score`. (default=`"knowledge"`) | | | Retrieval method. See [Query methods](#decision-matrix). (default=`"hybrid"`) | diff --git a/api-reference/v2/endpoint/source-relations.mdx b/api-reference/v2/endpoint/source-relations.mdx index 2ce36e37..a25d7161 100644 --- a/api-reference/v2/endpoint/source-relations.mdx +++ b/api-reference/v2/endpoint/source-relations.mdx @@ -49,7 +49,7 @@ curl -G 'https://api.hydradb.com/context/relations' \ | | Collection scope. If omitted, the default collection is used. | | | Maximum relation groups to return. Range `1` to `10000`. (default=`5000`) | | | Opaque pagination cursor from a previous response's `next_cursor`. (default=`null`) | -| | Principals to answer as for content from connectors without source-permission enforcement. Only relations from sources those principals may see are returned. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values; if `acl` is overridden, the response includes one `meta.warnings` entry with code `acl_overridden_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control). | +| | Principals to answer as for directly ingested knowledge and content from connectors without source-permission enforcement. Only relations from sources those principals may see are returned. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values; if `acl` is overridden, the response includes one `meta.warnings` entry with code `acl_overridden_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control). | diff --git a/api-reference/v2/endpoint/subgraph.mdx b/api-reference/v2/endpoint/subgraph.mdx index a2e53df0..d9811d3e 100644 --- a/api-reference/v2/endpoint/subgraph.mdx +++ b/api-reference/v2/endpoint/subgraph.mdx @@ -56,7 +56,7 @@ curl -G 'https://api.hydradb.com/context/slack_C0BE77_1788320073/subgraph' \ | | Which graph the `id` belongs to. The two graphs are completely separate. (default=`"knowledge"`) | | | Maximum traversal depth in hops. Range `1` to `10`. (default=`5`) | | | Maximum number of members returned. Range `1` to `1000`. When this clips the traversal, `is_truncated` is `true`. (default=`200`) | -| | Principals to answer as for content from connectors without source-permission enforcement. The subgraph then contains only items those principals may see, filtered at every hop. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values; if `acl` is overridden, the response includes one `meta.warnings` entry with code `acl_overridden_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control). | +| | Principals to answer as for directly ingested knowledge and content from connectors without source-permission enforcement. The subgraph then contains only items those principals may see, filtered at every hop. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values; if `acl` is overridden, the response includes one `meta.warnings` entry with code `acl_overridden_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control). | ## How items connect diff --git a/api-reference/v2/openapi.json b/api-reference/v2/openapi.json index 35924276..ebafc2e2 100644 --- a/api-reference/v2/openapi.json +++ b/api-reference/v2/openapi.json @@ -5345,7 +5345,7 @@ "list.V2ListContentRequest": { "properties": { "acl": { - "description": "Principals to answer as. For non-enforced connectors, only context visible to these principals is listed. Enforced connector content uses the authenticated caller instead. If sent and overridden, one `meta.warnings` entry has code `acl_overridden_by_connector_enforcement`.", + "description": "Principals to answer as. For directly ingested knowledge and non-enforced connectors, only context visible to these principals is listed. Enforced connector content uses the authenticated caller instead. If sent and overridden, one `meta.warnings` entry has code `acl_overridden_by_connector_enforcement`.", "items": { "type": "string" }, @@ -6241,7 +6241,7 @@ "search.QueryRequest": { "properties": { "acl": { - "description": "Principals to query as: emails or `user_email:`, `group:` or `domain:` principals. For non-enforced connectors, returns their context plus public and unrestricted context. Enforced connectors use the authenticated caller instead. If sent and overridden, one `meta.warnings` entry has code `acl_overridden_by_connector_enforcement`. Omit, `[]` or `[\"*\"]` to disable caller-supplied filtering for non-enforced connectors.", + "description": "Principals to query as: emails or `user_email:`, `group:` or `domain:` principals. For directly ingested knowledge and non-enforced connectors, returns their context plus public and unrestricted context. Enforced connectors use the authenticated caller instead. If sent and overridden, one `meta.warnings` entry has code `acl_overridden_by_connector_enforcement`. Omit, `[]` or `[\"*\"]` to disable caller-supplied filtering for non-enforced connectors.", "items": { "type": "string" }, @@ -9565,7 +9565,7 @@ } }, { - "description": "Principals to inspect as. For non-enforced connector content, only contexts visible to these principals can be inspected; a context that is not visible returns `404`. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values. If sent and overridden, one `meta.warnings` entry has code `acl_overridden_by_connector_enforcement`.", + "description": "Principals to inspect as. For directly ingested knowledge and non-enforced connector content, only contexts visible to these principals can be inspected; a context that is not visible returns `404`. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values. If sent and overridden, one `meta.warnings` entry has code `acl_overridden_by_connector_enforcement`.", "in": "query", "name": "acl", "schema": { @@ -9757,7 +9757,7 @@ } }, { - "description": "Principals to answer as. For non-enforced connector content, only results visible to these principals are returned. Enforced connector content uses the authenticated caller instead. Repeat the parameter or send a comma-separated list. If sent and overridden, one `meta.warnings` entry has code `acl_overridden_by_connector_enforcement`.", + "description": "Principals to answer as. For directly ingested knowledge and non-enforced connector content, only results visible to these principals are returned. Enforced connector content uses the authenticated caller instead. Repeat the parameter or send a comma-separated list. If sent and overridden, one `meta.warnings` entry has code `acl_overridden_by_connector_enforcement`.", "in": "query", "name": "acl", "schema": { @@ -10003,7 +10003,7 @@ } }, { - "description": "Principals to answer as. For non-enforced connector content, only contexts visible to these principals are returned, checked at every hop. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values. If sent and overridden, one `meta.warnings` entry has code `acl_overridden_by_connector_enforcement`.", + "description": "Principals to answer as. For directly ingested knowledge and non-enforced connector content, only contexts visible to these principals are returned, checked at every hop. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values. If sent and overridden, one `meta.warnings` entry has code `acl_overridden_by_connector_enforcement`.", "in": "query", "name": "acl", "schema": { @@ -10222,7 +10222,7 @@ } }, { - "description": "Principals allowed to read the returned contexts. For non-enforced connector content, only contexts visible to these principals are returned. Enforced connector content uses the authenticated caller instead for every returned context. If sent and overridden, one `meta.warnings` entry has code `acl_overridden_by_connector_enforcement`.", + "description": "Principals allowed to read the returned contexts. For directly ingested knowledge and non-enforced connector content, only contexts visible to these principals are returned. Enforced connector content uses the authenticated caller instead for every returned context. If sent and overridden, one `meta.warnings` entry has code `acl_overridden_by_connector_enforcement`.", "in": "query", "name": "acl", "schema": { diff --git a/essentials/v2/access-control.mdx b/essentials/v2/access-control.mdx index 1d066d85..8379a7a2 100644 --- a/essentials/v2/access-control.mdx +++ b/essentials/v2/access-control.mdx @@ -183,7 +183,7 @@ Access control works alongside [metadata filters](/essentials/v2/metadata): filt `POST /context/list` takes the same `acl` field with the same meaning. The `GET /context/chunks`, `GET /context/relations`, and `GET /context/subgraph` endpoints take it as a query parameter, repeated (`acl=a&acl=b`) or comma-separated. -For content from connectors without source-permission enforcement, access control is opt-in per request. A query without an `acl` field is not filtered by caller identity. For content from a connector with `follow_source_permissions` enabled, HydraDB enforces the authenticated caller's source permissions on every read instead. See [Permissions on synced content](/essentials/v2/connectors#enforce-source-permissions-as-the-caller) for how to enable it and how caller identities are selected. +For directly ingested knowledge and content from connectors without source-permission enforcement, access control is opt-in per request. A query without an `acl` field is not filtered by caller identity. For content from a connector with `follow_source_permissions` enabled, HydraDB enforces the authenticated caller's source permissions on every read instead. See [Permissions on synced content](/essentials/v2/connectors#enforce-source-permissions-as-the-caller) for how to enable it and how caller identities are selected. ## 2. Principals diff --git a/essentials/v2/query.mdx b/essentials/v2/query.mdx index 7a40c53f..70b9a044 100644 --- a/essentials/v2/query.mdx +++ b/essentials/v2/query.mdx @@ -223,7 +223,7 @@ Three fields bring in context beyond the passages that matched. All three are on ## 6. Query on behalf of a user -For content from connectors without source-permission enforcement, send the caller's email in `acl`, such as `"acl": ["grace@acme.com"]`, to filter results to documents that person may retrieve, plus public and unrestricted ones. Without `acl`, that content is not filtered by caller identity. For connectors with `follow_source_permissions` enabled, HydraDB uses the authenticated caller instead and ignores a request `acl` for that connector's content. API keys use the key creator's email; MCP OAuth and dashboard requests use the signed-in user. If you send `acl` while enforcement is enabled, a successful response includes one `meta.warnings` entry with code `acl_overridden_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control) and [Permissions on synced content](/essentials/v2/connectors#enforce-source-permissions-as-the-caller) for more. +For directly ingested knowledge and content from connectors without source-permission enforcement, send the caller's email in `acl`, such as `"acl": ["grace@acme.com"]`, to filter results to documents that person may retrieve, plus public and unrestricted ones. Without `acl`, that content is not filtered by caller identity. For connectors with `follow_source_permissions` enabled, HydraDB uses the authenticated caller instead and ignores a request `acl` for that connector's content. API keys use the key creator's email; MCP OAuth and dashboard requests use the signed-in user. If you send `acl` while enforcement is enabled, a successful response includes one `meta.warnings` entry with code `acl_overridden_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control) and [Permissions on synced content](/essentials/v2/connectors#enforce-source-permissions-as-the-caller) for more. ## Common mistakes From d94579d175063c0feab83047ca860bbc9085d22f Mon Sep 17 00:00:00 2001 From: Vorflux AI <249966464+vorflux[bot]@users.noreply.github.com> Date: Tue, 27 Oct 2026 05:43:58 +0000 Subject: [PATCH 4/8] docs(connectors): standardize ACL enforcement terms (PRO-3222 PRO-3223) Signed-off-by: Vorflux AI <249966464+vorflux[bot]@users.noreply.github.com> --- .../v2/endpoint/connectors-overview.mdx | 8 +-- .../v2/endpoint/create-connector.mdx | 6 +- api-reference/v2/endpoint/fetch-content.mdx | 2 +- .../v2/endpoint/list-connector-providers.mdx | 6 +- api-reference/v2/endpoint/list-documents.mdx | 2 +- api-reference/v2/endpoint/query.mdx | 4 +- .../v2/endpoint/source-relations.mdx | 2 +- api-reference/v2/endpoint/subgraph.mdx | 2 +- .../v2/endpoint/update-connector.mdx | 20 +++--- api-reference/v2/openapi.json | 66 +++++++++---------- essentials/v2/access-control.mdx | 32 ++++----- essentials/v2/connectors.mdx | 26 ++++---- essentials/v2/query.mdx | 2 +- 13 files changed, 90 insertions(+), 88 deletions(-) diff --git a/api-reference/v2/endpoint/connectors-overview.mdx b/api-reference/v2/endpoint/connectors-overview.mdx index d7b5ef6d..fefcdae2 100644 --- a/api-reference/v2/endpoint/connectors-overview.mdx +++ b/api-reference/v2/endpoint/connectors-overview.mdx @@ -25,7 +25,7 @@ Check on it: Change it: -- [Update Connector](/api-reference/v2/endpoint/update-connector): `PATCH /connectors/{id}` changes the sync interval, connector-level instructions, credentials or the owner-only source-permission enforcement setting. +- [Update Connector](/api-reference/v2/endpoint/update-connector): `PATCH /connectors/{id}` changes the sync interval, connector-level instructions, credentials or the owner-only ACL enforcement setting. - [Update Connector Resource](/api-reference/v2/endpoint/update-connector-resource): `PATCH /connectors/{id}/resources/{resource_id}` changes one resource's instructions or access rule. - [Add Connector Resource](/api-reference/v2/endpoint/add-connector-resource): `POST /connectors/{id}/resources` adds one new resource. - [Delete Connector Resource](/api-reference/v2/endpoint/delete-connector-resource): `DELETE /connectors/{id}/resources/{resource_id}` stops syncing a resource. @@ -37,7 +37,7 @@ Change it: 2. `GET /connectors/{id}/discover` to see which resources are available. 3. `POST /connectors/{id}/configure` with the resources to sync. This starts the first sync. 4. `GET /connectors/{id}/status` until `status` is `healthy` and `lifecycle` is `active`. -5. `POST /query` to search the database and collection chosen during configuration. For content from connectors without source-permission enforcement, send the caller's identity as `acl`; omitting it leaves those results unfiltered. Enforced connectors use the authenticated caller instead. `query_apps` is enabled by default. +5. `POST /query` to search the database and collection chosen during configuration. For content from connectors without ACL enforcement, send the caller's identity as `acl`; omitting it leaves those results unfiltered. Enforced connectors use the authenticated caller instead. `query_apps` is enabled by default. After that, syncs run every `sync_interval_seconds` (one hour by default). Call `POST /connectors/{id}/sync` only when you need data sooner. @@ -46,7 +46,7 @@ After that, syncs run every `sync_interval_seconds` (one hour by default). Call To change a resource that is already configured, use `PATCH /connectors/{id}/resources/{resource_id}` or `POST /connectors/{id}/configure`. `POST /connectors/{id}/resources` adds new resources only: on an existing `resource_id` it returns `409` and changes nothing. - Instructions or access rule on one resource: `PATCH /connectors/{id}/resources/{resource_id}`. Only the fields you send change. -- Instructions, sync interval, credentials or source-permission enforcement for the whole connector: `PATCH /connectors/{id}`. Only the fields you send change. Only a workspace owner in a signed-in dashboard session can set `follow_source_permissions`; API keys cannot change it. +- Instructions, sync interval, credentials or ACL enforcement for the whole connector: `PATCH /connectors/{id}`. Only the fields you send change. Only a workspace owner in a signed-in dashboard session can set `enforce_acl`; API keys cannot change it. - Name, type, database, collection or metadata of resources: `POST /connectors/{id}/configure`. Resources you leave out of the list are not touched. For each resource you list, send `name` and `resource_type` every time, because omitted values are cleared. Its sync position, instructions and access rule are kept. - A brand new resource: `POST /connectors/{id}/configure` or `POST /connectors/{id}/resources`. @@ -61,7 +61,7 @@ Authorization: Bearer $HYDRA_DB_API_KEY API-Version: 2 ``` -To set `follow_source_permissions`, use a workspace owner's signed-in dashboard session instead; API-key-authenticated requests cannot set it. +To set `enforce_acl`, use a workspace owner's signed-in dashboard session instead; API-key-authenticated requests cannot set it. ## Key concepts diff --git a/api-reference/v2/endpoint/create-connector.mdx b/api-reference/v2/endpoint/create-connector.mdx index 3c171f3a..ba2263b5 100644 --- a/api-reference/v2/endpoint/create-connector.mdx +++ b/api-reference/v2/endpoint/create-connector.mdx @@ -12,7 +12,7 @@ Optional settings you can also pass here, and change later with [Update Connecto - `custom_instructions`: guidance for how this connector's documents are interpreted and indexed. See [Custom Ingestion Instructions](/essentials/v2/connectors#custom-ingestion-instructions). - `sync_interval_seconds`: how often scheduled syncs run. Omit it for the provider default (one hour for most providers). -- `follow_source_permissions`: whether content reads always enforce the authenticated caller's source permissions for this connector. It defaults to `false` when omitted. Only a workspace owner in a signed-in dashboard session can set it, and `true` requires the provider to report `rbac_support: true`. API-key-authenticated requests must omit this field. An owner can enable or change it later with [Update Connector](/api-reference/v2/endpoint/update-connector) or in the dashboard. See [Permissions on synced content](/essentials/v2/connectors#enforce-source-permissions-as-the-caller) for how caller identity and request `acl` behave. +- `enforce_acl`: whether content reads always enforce ACL for the authenticated caller for this connector. It defaults to `false` when omitted. Only a workspace owner in a signed-in dashboard session can set it, and `true` requires the provider to report `acl_supported: true`. API-key-authenticated requests must omit this field. An owner can enable or change it later with [Update Connector](/api-reference/v2/endpoint/update-connector) or in the dashboard. See [ACL on synced content](/essentials/v2/connectors#enforce-acl) for how caller identity and request `acl` behave. @@ -71,7 +71,7 @@ curl -X POST 'https://api.hydradb.com/connectors' \ "provider_account_scope": "T12345ACME", "lifecycle": "pending_setup", "sync_status": "idle", - "follow_source_permissions": false, + "enforce_acl": false, "sync_interval_seconds": 3600, "next_sync_at": "2026-06-01T12:05:00Z", "first_sync_at": "2026-06-01T12:05:00Z", @@ -85,7 +85,7 @@ curl -X POST 'https://api.hydradb.com/connectors' \ - `400`: `provider` or `database` is missing, the provider is unknown, or a setting such as `sync_interval_seconds` is out of range. - `402`: your plan's connector limit is reached. -- `403`: the provider is not available to your organization, or the request tries to set `follow_source_permissions` without a workspace owner's signed-in dashboard session. +- `403`: the provider is not available to your organization, or the request tries to set `enforce_acl` without a workspace owner's signed-in dashboard session. - `422`: `credentials` does not match the provider's `credential_schema`.
diff --git a/api-reference/v2/endpoint/fetch-content.mdx b/api-reference/v2/endpoint/fetch-content.mdx index fa8a4e32..587279a4 100644 --- a/api-reference/v2/endpoint/fetch-content.mdx +++ b/api-reference/v2/endpoint/fetch-content.mdx @@ -49,7 +49,7 @@ curl -G 'https://api.hydradb.com/context/inspect' \ | | Collection scope. If omitted, the default collection is used. | | | What to return. See [Fetch modes](#fetch-modes). (default=`"both"`) | | | TTL of the presigned URL (when `mode` includes `url`). Range `60` to `604800` (7 days). (default=`3600`) | -| | Principals to answer as for directly ingested knowledge and content from connectors without source-permission enforcement. A source they cannot see returns the same `404` as a missing one. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values; if `acl` is overridden, the response includes one `meta.warnings` entry with code `acl_overridden_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control). | +| | Principals to answer as for directly ingested knowledge and content from connectors without ACL enforcement. A source they cannot see returns the same `404` as a missing one. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values; if `acl` is overridden, the response includes one `meta.warnings` entry with code `acl_ignored_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control). | ## Fetch modes diff --git a/api-reference/v2/endpoint/list-connector-providers.mdx b/api-reference/v2/endpoint/list-connector-providers.mdx index 1986c8b3..b3790b64 100644 --- a/api-reference/v2/endpoint/list-connector-providers.mdx +++ b/api-reference/v2/endpoint/list-connector-providers.mdx @@ -53,8 +53,8 @@ TypeScript SDK 2.1.7 requires the explicit authorization header for this method. "supported": true, "moveit_support": false, "webhook_support": false, - "rbac_support": true, - "rbac_description": "Captures channel-level access: public channels are visible to the whole workspace, private channels only to their members.", + "acl_supported": true, + "acl_description": "Captures channel-level access: public channels are visible to the whole workspace, private channels only to their members.", "is_alpha": false, "is_beta": false, "rank": 1 @@ -96,7 +96,7 @@ TypeScript SDK 2.1.7 requires the explicit authorization header for this method. Only providers you can connect are listed, so `supported` is always `true`. `webhook_support` is `true` for providers whose data arrives by webhook instead of scheduled syncs. `rank` is `null` for providers without a display position; they are listed last, alphabetically. -`rbac_support` indicates whether the provider captures source permissions as document access rules. When it is `true`, `rbac_description` summarizes the captured permissions. `follow_source_permissions` can only be enabled for a connector when its provider reports `rbac_support: true`; see [Permissions on synced content](/essentials/v2/connectors#enforce-source-permissions-as-the-caller). +`acl_supported` indicates whether the provider captures ACL as document access rules. When it is `true`, `acl_description` summarizes the captured ACL. `enforce_acl` can only be enabled for a connector when its provider reports `acl_supported: true`; see [ACL on synced content](/essentials/v2/connectors#enforce-acl). ## One provider diff --git a/api-reference/v2/endpoint/list-documents.mdx b/api-reference/v2/endpoint/list-documents.mdx index 0601cf99..6811c179 100644 --- a/api-reference/v2/endpoint/list-documents.mdx +++ b/api-reference/v2/endpoint/list-documents.mdx @@ -76,7 +76,7 @@ curl -X POST 'https://api.hydradb.com/context/list' \ | | Items per page, from `1` to `100`. (default=`50`) | | | Structured exact-match filters. See [Filters](#filters). (default=`null`) | | | Field projection. Only the listed fields plus `id`, `database`, `collection` are populated. Only applies to `type=knowledge`. (default=`null`, all fields) | -| | Principals to list as for directly ingested knowledge and knowledge from connectors without source-permission enforcement. Enforced connector content uses the authenticated caller instead. If supplied `acl` is overridden, the response includes one `meta.warnings` entry with code `acl_overridden_by_connector_enforcement`. Omitted, `[]`, or `["*"]` disables caller-supplied filtering outside enforced connectors. Ignored for `type=memory`. See [Access Control](/essentials/v2/access-control). | +| | Principals to list as for directly ingested knowledge and knowledge from connectors without ACL enforcement. Enforced connector content uses the authenticated caller instead. If supplied `acl` is overridden, the response includes one `meta.warnings` entry with code `acl_ignored_by_connector_enforcement`. Omitted, `[]`, or `["*"]` disables caller-supplied filtering outside enforced connectors. Ignored for `type=memory`. See [Access Control](/essentials/v2/access-control). | ### Filters diff --git a/api-reference/v2/endpoint/query.mdx b/api-reference/v2/endpoint/query.mdx index dd77d3a0..b7bc7ce4 100644 --- a/api-reference/v2/endpoint/query.mdx +++ b/api-reference/v2/endpoint/query.mdx @@ -316,7 +316,7 @@ result = client.query( | | Multi-collection scope. Send a list of collection IDs for equal weighting, or an object mapping collection ID to a positive relative weight (at most one decimal place, e.g. `{"finance": 1.5, "legal": 0.8}`) to bias ranking. Up to 100 collections. Do not combine with `collection`. | | | Query terms or natural-language question. Cannot be empty. Maximum 5,000 words. | | | Exact source titles, matched case-insensitively. Matches any listed title, then intersects with `ids` if both are sent. | -| | Caller identities used to filter directly ingested knowledge and content from connectors without source-permission enforcement. Omitting `acl`, sending `[]`, or sending `["*"]` disables this caller-supplied filtering. For enforced connectors, HydraDB uses the authenticated caller instead and ignores this field for their content. If you send `acl` while enforcement is enabled, a successful response includes one `meta.warnings` entry with code `acl_overridden_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control) and [Permissions on synced content](/essentials/v2/connectors#enforce-source-permissions-as-the-caller). | +| | Caller identities used to filter directly ingested knowledge and content from connectors without ACL enforcement. Omitting `acl`, sending `[]`, or sending `["*"]` disables this caller-supplied filtering. For enforced connectors, HydraDB uses the authenticated caller instead and ignores this field for their content. If you send `acl` while enforcement is enabled, a successful response includes one `meta.warnings` entry with code `acl_ignored_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control) and [ACL on synced content](/essentials/v2/connectors#enforce-acl). | | | Omit for the result object with `llm_prompt`. `"structured"` leaves out the prompt string. `"markdown"` returns the prompt string directly as `data`. | | | What to query. `"all"` runs knowledge and memory in parallel over the same scope and merges by `relevancy_score`. (default=`"knowledge"`) | | | Retrieval method. See [Query methods](#decision-matrix). (default=`"hybrid"`) | @@ -348,7 +348,7 @@ Metadata filters work like SQL `WHERE` clauses. Top-level `metadata_filters` key } ``` -See [Metadata and Filters](/essentials/v2/metadata#3-filter-operators) for operators and examples. Filters narrow results. They do not replace the caller's `acl` or connector-enforced source permissions. +See [Metadata and Filters](/essentials/v2/metadata#3-filter-operators) for operators and examples. Filters narrow results. They do not replace the caller's `acl` or connector ACL enforcement. ### Decision matrix diff --git a/api-reference/v2/endpoint/source-relations.mdx b/api-reference/v2/endpoint/source-relations.mdx index a25d7161..de50728f 100644 --- a/api-reference/v2/endpoint/source-relations.mdx +++ b/api-reference/v2/endpoint/source-relations.mdx @@ -49,7 +49,7 @@ curl -G 'https://api.hydradb.com/context/relations' \ | | Collection scope. If omitted, the default collection is used. | | | Maximum relation groups to return. Range `1` to `10000`. (default=`5000`) | | | Opaque pagination cursor from a previous response's `next_cursor`. (default=`null`) | -| | Principals to answer as for directly ingested knowledge and content from connectors without source-permission enforcement. Only relations from sources those principals may see are returned. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values; if `acl` is overridden, the response includes one `meta.warnings` entry with code `acl_overridden_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control). | +| | Principals to answer as for directly ingested knowledge and content from connectors without ACL enforcement. Only relations from sources those principals may see are returned. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values; if `acl` is overridden, the response includes one `meta.warnings` entry with code `acl_ignored_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control). | diff --git a/api-reference/v2/endpoint/subgraph.mdx b/api-reference/v2/endpoint/subgraph.mdx index d9811d3e..cf1b1ca4 100644 --- a/api-reference/v2/endpoint/subgraph.mdx +++ b/api-reference/v2/endpoint/subgraph.mdx @@ -56,7 +56,7 @@ curl -G 'https://api.hydradb.com/context/slack_C0BE77_1788320073/subgraph' \ | | Which graph the `id` belongs to. The two graphs are completely separate. (default=`"knowledge"`) | | | Maximum traversal depth in hops. Range `1` to `10`. (default=`5`) | | | Maximum number of members returned. Range `1` to `1000`. When this clips the traversal, `is_truncated` is `true`. (default=`200`) | -| | Principals to answer as for directly ingested knowledge and content from connectors without source-permission enforcement. The subgraph then contains only items those principals may see, filtered at every hop. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values; if `acl` is overridden, the response includes one `meta.warnings` entry with code `acl_overridden_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control). | +| | Principals to answer as for directly ingested knowledge and content from connectors without ACL enforcement. The subgraph then contains only items those principals may see, filtered at every hop. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values; if `acl` is overridden, the response includes one `meta.warnings` entry with code `acl_ignored_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control). | ## How items connect diff --git a/api-reference/v2/endpoint/update-connector.mdx b/api-reference/v2/endpoint/update-connector.mdx index 1039f0a3..141ca447 100644 --- a/api-reference/v2/endpoint/update-connector.mdx +++ b/api-reference/v2/endpoint/update-connector.mdx @@ -4,7 +4,7 @@ description: "Change a connector's instructions, sync interval or credentials in openapi: "api-reference/v2/openapi.json PATCH /connectors/{id}" --- -Update a connector's instructions, sync interval, credentials, or source-permission enforcement. Omitted fields keep their existing values. +Update a connector's instructions, sync interval, credentials, or ACL enforcement. Omitted fields keep their existing values. - HydraDB validates every field before saving. Invalid input changes nothing. - Credentials are saved before other settings. If a server error occurs afterward, only the credentials may have changed. Retrying the same request is safe. @@ -12,19 +12,19 @@ Update a connector's instructions, sync interval, credentials, or source-permiss - `custom_instructions` applies to resources without their own instructions. Maximum 4,000 characters. Send `""` to clear it. Changes affect future syncs. See [Custom Ingestion Instructions](/essentials/v2/connectors#custom-ingestion-instructions). - `sync_interval_seconds` reschedules the next sync. Stay within the returned `min_sync_interval_seconds` and `max_sync_interval_seconds`, or send `0` for the provider default. - `credentials` reconnects the existing connector. Send the provider's complete credential set. Resources and saved sync positions are preserved. -- `follow_source_permissions` enables or disables caller-bound enforcement of this connector's captured source permissions. Existing connectors remain `false` until an owner enables it. Send `true` to enforce captured permissions on every content read, or `false` to return to opt-in request `acl` filtering. Omit it to keep the current value. The change takes effect on the next content request for already-synced documents and does not require re-ingestion. Only a workspace owner in a signed-in dashboard session can set it; `true` requires the provider to report `rbac_support: true`. API-key-authenticated requests cannot set it. See [Permissions on synced content](/essentials/v2/connectors#enforce-source-permissions-as-the-caller) and [Access Control](/essentials/v2/access-control). +- `enforce_acl` enables or disables caller-bound enforcement of this connector's captured ACL. Existing connectors remain `false` until an owner enables it. Send `true` to enforce captured ACL on every content read, or `false` to return to opt-in request `acl` filtering. Omit it to keep the current value. The change takes effect on the next content request for already-synced documents and does not require re-ingestion. Only a workspace owner in a signed-in dashboard session can set it; `true` requires the provider to report `acl_supported: true`. API-key-authenticated requests cannot set it. See [ACL on synced content](/essentials/v2/connectors#enforce-acl) and [Access Control](/essentials/v2/access-control). -To enable enforcement later, send this field in a separate PATCH request, or use **Follow source permissions** in the dashboard's connector settings: +To enable enforcement later, send this field in a separate PATCH request, or use **Enforce ACL** in the dashboard's connector settings: ```json { - "follow_source_permissions": true + "enforce_acl": true } ``` -Do not combine `follow_source_permissions` and `credentials` in the same PATCH request. Send them in separate requests. +Do not combine `enforce_acl` and `credentials` in the same PATCH request. Send them in separate requests. -Only `custom_instructions`, `sync_interval_seconds`, `credentials`, and `follow_source_permissions` can be updated. A connector's `name`, `database`, `collection` and `provider_account_scope` cannot be changed after creation. Omit them from the request; unsupported fields can cause a `400` response. +Only `custom_instructions`, `sync_interval_seconds`, `credentials`, and `enforce_acl` can be updated. A connector's `name`, `database`, `collection` and `provider_account_scope` cannot be changed after creation. Omit them from the request; unsupported fields can cause a `400` response. @@ -68,7 +68,7 @@ curl -X PATCH 'https://api.hydradb.com/connectors/{id}' \ { "connector_id": "{connector_id}", "sync_interval_seconds": 3600, - "follow_source_permissions": false, + "enforce_acl": false, "next_sync_at": "2026-06-01T13:00:00Z", "min_sync_interval_seconds": 300, "max_sync_interval_seconds": 604800, @@ -82,10 +82,10 @@ curl -X PATCH 'https://api.hydradb.com/connectors/{id}' \ ## Errors -- `400`: the request includes an unsupported field, `follow_source_permissions` is combined with `credentials`, the provider does not report `rbac_support` for `follow_source_permissions: true`, `custom_instructions` is over 4,000 characters, or `sync_interval_seconds` is outside the provider's range. Nothing is changed. -- `403`: the request tries to set `follow_source_permissions` without a workspace owner's signed-in dashboard session. +- `400`: the request includes an unsupported field, `enforce_acl` is combined with `credentials`, the provider does not report `acl_supported` for `enforce_acl: true`, `custom_instructions` is over 4,000 characters, or `sync_interval_seconds` is outside the provider's range. Nothing is changed. +- `403`: the request tries to set `enforce_acl` without a workspace owner's signed-in dashboard session. - `404`: no connector with this id in your organization. -- `409`: another update changed the permission setting at the same time. Reload the connector and retry. +- `409`: another update changed ACL enforcement at the same time. Reload the connector and retry. - `422`: `credentials` does not match the provider's `credential_schema`. - `503`: the provider capability catalog is unavailable. Retry the request. diff --git a/api-reference/v2/openapi.json b/api-reference/v2/openapi.json index ebafc2e2..53ca8ba8 100644 --- a/api-reference/v2/openapi.json +++ b/api-reference/v2/openapi.json @@ -2908,12 +2908,12 @@ "handler.ResponseWarning": { "properties": { "code": { - "description": "Code identifies the warning type, such as acl_overridden_by_connector_enforcement.", + "description": "Code identifies the warning type, such as acl_ignored_by_connector_enforcement.", "type": "string" }, "message": { "description": "Human-readable explanation of the warning.", - "example": "The caller-supplied acl was ignored for content from connectors that enforce source permissions.", + "example": "This connector enforces ACL, so the request's acl was ignored.", "type": "string" } }, @@ -2980,12 +2980,12 @@ "null" ] }, - "rbac_description": { - "description": "One-line summary of the provider permissions captured as document access rules. Present when `rbac_support` is true.", + "acl_description": { + "description": "One-line summary of the provider ACL captured as document access rules. Present when `acl_supported` is true.", "type": "string" }, - "rbac_support": { - "description": "True when the provider captures source permissions as document access rules. Connector source-permission enforcement can be enabled only when this is true.", + "acl_supported": { + "description": "True when the provider captures ACL as document access rules. Connector ACL enforcement can be enabled only when this is true.", "example": true, "type": "boolean" }, @@ -3161,8 +3161,8 @@ "description": "RFC3339 timestamp of the first sync that sent at least one object for ingestion. Empty until then.", "type": "string" }, - "follow_source_permissions": { - "description": "Whether source permissions are enforced. False when unsupported. When true, reads use the authenticated caller; otherwise request `acl` remains an opt-in filter.", + "enforce_acl": { + "description": "Whether ACL enforcement is enabled. False when unsupported. When true, reads use the authenticated caller; otherwise request `acl` remains an opt-in filter.", "example": true, "type": "boolean" }, @@ -3308,8 +3308,8 @@ "example": "acme_corp", "type": "string" }, - "follow_source_permissions": { - "description": "Optional owner-only setting; defaults to false. True requires provider `rbac_support` and enables caller-bound reads; false keeps request `acl` as an opt-in filter.", + "enforce_acl": { + "description": "Optional owner-only setting; defaults to false. True requires provider `acl_supported` and enables caller-bound reads; false keeps request `acl` as an opt-in filter.", "example": true, "type": "boolean" }, @@ -3398,8 +3398,8 @@ "description": "RFC3339 timestamp when the first scheduled sync runs.", "type": "string" }, - "follow_source_permissions": { - "description": "Whether source permissions are enforced. False when unsupported. When true, reads use the authenticated caller; otherwise request `acl` remains an opt-in filter.", + "enforce_acl": { + "description": "Whether ACL enforcement is enabled. False when unsupported. When true, reads use the authenticated caller; otherwise request `acl` remains an opt-in filter.", "example": true, "type": "boolean" }, @@ -3919,8 +3919,8 @@ "description": "Ingestion and indexing instructions for every resource on this connector that has no instructions of its own. Omit to leave unchanged; `\"\"` clears. Up to 4000 characters, applied from the next sync.", "type": "string" }, - "follow_source_permissions": { - "description": "Set whether the connector follows source permissions. Omit to keep the current value; only a workspace owner may set it. True requires provider catalog `rbac_support`.", + "enforce_acl": { + "description": "Set whether the connector enforces ACL. Omit to keep the current value; only a workspace owner may set it. True requires provider catalog `acl_supported`.", "example": true, "type": "boolean" }, @@ -3950,8 +3950,8 @@ "example": true, "type": "boolean" }, - "follow_source_permissions": { - "description": "Whether source permissions are enforced. False when unsupported. When true, reads use the authenticated caller; otherwise request `acl` remains an opt-in filter.", + "enforce_acl": { + "description": "Whether ACL enforcement is enabled. False when unsupported. When true, reads use the authenticated caller; otherwise request `acl` remains an opt-in filter.", "example": true, "type": "boolean" }, @@ -4386,10 +4386,10 @@ "is_beta": true, "moveit_support": true, "provider": "slack", - "rbac_support": true, + "acl_supported": true, "supported": true, "webhook_support": true, - "rbac_description": "Captures channel-level access: public channels are visible to the workspace, private channels only to their members." + "acl_description": "Captures channel-level access: public channels are visible to the workspace, private channels only to their members." } ], "items": { @@ -4871,11 +4871,11 @@ "x-deprecated": "true" }, "warnings": { - "description": "Non-fatal response notices. When request `acl` is overridden for enforced connector content, exactly one warning has code `acl_overridden_by_connector_enforcement`.", + "description": "Non-fatal response notices. When request `acl` is overridden for enforced connector content, exactly one warning has code `acl_ignored_by_connector_enforcement`.", "example": [ { - "code": "acl_overridden_by_connector_enforcement", - "message": "The caller-supplied acl was ignored for content from connectors that enforce source permissions." + "code": "acl_ignored_by_connector_enforcement", + "message": "This connector enforces ACL, so the request's acl was ignored." } ], "items": { @@ -5345,7 +5345,7 @@ "list.V2ListContentRequest": { "properties": { "acl": { - "description": "Principals to answer as. For directly ingested knowledge and non-enforced connectors, only context visible to these principals is listed. Enforced connector content uses the authenticated caller instead. If sent and overridden, one `meta.warnings` entry has code `acl_overridden_by_connector_enforcement`.", + "description": "Principals to answer as. For directly ingested knowledge and non-enforced connectors, only context visible to these principals is listed. Enforced connector content uses the authenticated caller instead. If sent and overridden, one `meta.warnings` entry has code `acl_ignored_by_connector_enforcement`.", "items": { "type": "string" }, @@ -6241,7 +6241,7 @@ "search.QueryRequest": { "properties": { "acl": { - "description": "Principals to query as: emails or `user_email:`, `group:` or `domain:` principals. For directly ingested knowledge and non-enforced connectors, returns their context plus public and unrestricted context. Enforced connectors use the authenticated caller instead. If sent and overridden, one `meta.warnings` entry has code `acl_overridden_by_connector_enforcement`. Omit, `[]` or `[\"*\"]` to disable caller-supplied filtering for non-enforced connectors.", + "description": "Principals to query as: emails or `user_email:`, `group:` or `domain:` principals. For directly ingested knowledge and non-enforced connectors, returns their context plus public and unrestricted context. Enforced connectors use the authenticated caller instead. If sent and overridden, one `meta.warnings` entry has code `acl_ignored_by_connector_enforcement`. Omit, `[]` or `[\"*\"]` to disable caller-supplied filtering for non-enforced connectors.", "items": { "type": "string" }, @@ -8078,7 +8078,7 @@ "x-fern-sdk-method-name": "list" }, "post": { - "description": "Create a connector for a provider and store its credentials. `follow_source_permissions` defaults to false when omitted, so writers may create connectors without choosing the setting. Only a workspace owner in a human dashboard session may explicitly set it, and true is accepted only when the provider catalog reports rbac_support. When true, content reads always use the authenticated caller; when false, request `acl` remains an opt-in filter.", + "description": "Create a connector for a provider and store its credentials. `enforce_acl` defaults to false when omitted, so writers may create connectors without choosing the setting. Only a workspace owner in a human dashboard session may explicitly set it, and true is accepted only when the provider catalog reports acl_supported. When true, content reads always use the authenticated caller; when false, request `acl` remains an opt-in filter.", "requestBody": { "content": { "application/json": { @@ -8119,7 +8119,7 @@ } } }, - "description": "Setting follow_source_permissions requires a workspace owner in a signed-in dashboard session." + "description": "Setting enforce_acl requires a workspace owner in a signed-in dashboard session." }, "500": { "content": { @@ -8157,7 +8157,7 @@ }, "/connectors/providers": { "get": { - "description": "Lists the providers you can connect, including whether source-permission capture is supported (`rbac_support`) and its summary (`rbac_description`). With `id`, describes one provider: its searchable object types and fields (with `filter_key`), `credential_schema`, and `setup_guide` when needed.", + "description": "Lists the providers you can connect, including whether ACL capture is supported (`acl_supported`) and its summary (`acl_description`). With `id`, describes one provider: its searchable object types and fields (with `filter_key`), `credential_schema`, and `setup_guide` when needed.", "parameters": [ { "description": "Provider name (e.g. slack, gmail). Omit to list all.", @@ -8330,7 +8330,7 @@ "x-fern-sdk-method-name": "get" }, "patch": { - "description": "Update the supplied connector settings. Use `credentials` to reconnect, `sync_interval_seconds` to change cadence, `custom_instructions` to change ingestion instructions, or `follow_source_permissions` to set the owner-only enforcement mode. True requires provider catalog `rbac_support`; when enabled, content reads use the authenticated caller, while false keeps request `acl` as an opt-in filter.", + "description": "Update the supplied connector settings. Use `credentials` to reconnect, `sync_interval_seconds` to change cadence, `custom_instructions` to change ingestion instructions, or `enforce_acl` to set the owner-only enforcement mode. True requires provider catalog `acl_supported`; when enabled, content reads use the authenticated caller, while false keeps request `acl` as an opt-in filter.", "parameters": [ { "description": "Connector ID", @@ -8383,7 +8383,7 @@ } } }, - "description": "Setting follow_source_permissions requires a workspace owner in a signed-in dashboard session." + "description": "Setting enforce_acl requires a workspace owner in a signed-in dashboard session." }, "404": { "content": { @@ -8403,7 +8403,7 @@ } } }, - "description": "The source-permissions revision changed after the connector was loaded; reload and retry. If the connector was deleted, the handler returns 404." + "description": "The ACL enforcement revision changed after the connector was loaded; reload and retry. If the connector was deleted, the handler returns 404." }, "500": { "content": { @@ -9565,7 +9565,7 @@ } }, { - "description": "Principals to inspect as. For directly ingested knowledge and non-enforced connector content, only contexts visible to these principals can be inspected; a context that is not visible returns `404`. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values. If sent and overridden, one `meta.warnings` entry has code `acl_overridden_by_connector_enforcement`.", + "description": "Principals to inspect as. For directly ingested knowledge and non-enforced connector content, only contexts visible to these principals can be inspected; a context that is not visible returns `404`. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values. If sent and overridden, one `meta.warnings` entry has code `acl_ignored_by_connector_enforcement`.", "in": "query", "name": "acl", "schema": { @@ -9757,7 +9757,7 @@ } }, { - "description": "Principals to answer as. For directly ingested knowledge and non-enforced connector content, only results visible to these principals are returned. Enforced connector content uses the authenticated caller instead. Repeat the parameter or send a comma-separated list. If sent and overridden, one `meta.warnings` entry has code `acl_overridden_by_connector_enforcement`.", + "description": "Principals to answer as. For directly ingested knowledge and non-enforced connector content, only results visible to these principals are returned. Enforced connector content uses the authenticated caller instead. Repeat the parameter or send a comma-separated list. If sent and overridden, one `meta.warnings` entry has code `acl_ignored_by_connector_enforcement`.", "in": "query", "name": "acl", "schema": { @@ -10003,7 +10003,7 @@ } }, { - "description": "Principals to answer as. For directly ingested knowledge and non-enforced connector content, only contexts visible to these principals are returned, checked at every hop. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values. If sent and overridden, one `meta.warnings` entry has code `acl_overridden_by_connector_enforcement`.", + "description": "Principals to answer as. For directly ingested knowledge and non-enforced connector content, only contexts visible to these principals are returned, checked at every hop. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values. If sent and overridden, one `meta.warnings` entry has code `acl_ignored_by_connector_enforcement`.", "in": "query", "name": "acl", "schema": { @@ -10222,7 +10222,7 @@ } }, { - "description": "Principals allowed to read the returned contexts. For directly ingested knowledge and non-enforced connector content, only contexts visible to these principals are returned. Enforced connector content uses the authenticated caller instead for every returned context. If sent and overridden, one `meta.warnings` entry has code `acl_overridden_by_connector_enforcement`.", + "description": "Principals allowed to read the returned contexts. For directly ingested knowledge and non-enforced connector content, only contexts visible to these principals are returned. Enforced connector content uses the authenticated caller instead for every returned context. If sent and overridden, one `meta.warnings` entry has code `acl_ignored_by_connector_enforcement`.", "in": "query", "name": "acl", "schema": { diff --git a/essentials/v2/access-control.mdx b/essentials/v2/access-control.mdx index 8379a7a2..cdf57e64 100644 --- a/essentials/v2/access-control.mdx +++ b/essentials/v2/access-control.mdx @@ -1,17 +1,17 @@ --- title: "Access Control" -description: "Restrict which people can retrieve a document, by declaring permissions yourself or letting connectors copy them from the source app." +description: "Restrict which people can retrieve a document by setting ACLs yourself or letting connectors capture them." --- By default, a query can retrieve any document in its collection. Access control changes that: a document carries an `acl`, the list of people allowed to retrieve it, and a query carries an `acl` naming who is asking. HydraDB returns only matching documents that person is allowed to see. This is how an internal search product keeps one employee's query from surfacing a private Slack channel or a restricted Drive file that belongs to someone else. -ACLs apply to knowledge sources. You set one at ingest on an [app source](/essentials/v2/app-sources), or later on an existing source ([section 4](#4-change-or-revoke-access)). [Connectors](/essentials/v2/connectors) can capture app permissions or apply your resource rules. [Memories](/essentials/v2/memories) are scoped per user with `collection` instead. +ACLs apply to knowledge sources. You set one at ingest on an [app source](/essentials/v2/app-sources), or later on an existing source ([section 4](#4-change-or-revoke-access)). [Connectors](/essentials/v2/connectors) can capture provider ACLs or apply your resource rules. [Memories](/essentials/v2/memories) are scoped per user with `collection` instead. In this guide: 1. [Set an ACL on an item and query as someone](#1-set-an-acl-on-an-item-and-query-as-someone): restrict a Slack message, then query as one person. 2. [Principals](#2-principals): the five identity forms, and what a query's `acl` list can contain. -3. [Let connectors capture permissions](#3-let-connectors-capture-permissions): which providers copy their own permissions, and how your own rule per resource fits in. +3. [Let connectors capture ACL](#3-let-connectors-capture-acl): which providers supply ACLs, and how your own resource rule fits in. 4. [Change or revoke access](#4-change-or-revoke-access): editing an ACL without re-ingesting, and when each change takes effect. 5. [Common mistakes](#common-mistakes) and [related pages](#related). @@ -183,7 +183,7 @@ Access control works alongside [metadata filters](/essentials/v2/metadata): filt `POST /context/list` takes the same `acl` field with the same meaning. The `GET /context/chunks`, `GET /context/relations`, and `GET /context/subgraph` endpoints take it as a query parameter, repeated (`acl=a&acl=b`) or comma-separated. -For directly ingested knowledge and content from connectors without source-permission enforcement, access control is opt-in per request. A query without an `acl` field is not filtered by caller identity. For content from a connector with `follow_source_permissions` enabled, HydraDB enforces the authenticated caller's source permissions on every read instead. See [Permissions on synced content](/essentials/v2/connectors#enforce-source-permissions-as-the-caller) for how to enable it and how caller identities are selected. +For directly ingested knowledge and content from connectors without ACL enforcement, access control is opt-in per request. A query without an `acl` field is not filtered by caller identity. For content from a connector with `enforce_acl` enabled, HydraDB enforces ACL for the authenticated caller on every read instead. See [ACL on synced content](/essentials/v2/connectors#enforce-acl) for how to enable it and how caller identities are selected. ## 2. Principals @@ -206,7 +206,7 @@ Principals are lowercased, trimmed, and deduplicated on the way in. `__public__` | You send | Behavior | |---|---| -| No `acl` field | No caller-supplied ACL filtering. Connectors with source-permission enforcement still apply the authenticated caller's permissions. | +| No `acl` field | No caller-supplied ACL filtering. Connectors with ACL enforcement still apply ACL for the authenticated caller. | | `"acl": []` | Same as omitting it. On a query, an empty list does not mean nobody. | | `"acl": ["*"]` | Same as omitting it. An explicit "search as an administrator" for content without connector enforcement. | | `"acl": ["grace@acme.com"]` | Filtered to what Grace may see on content without connector enforcement: her own documents, anything shared with `domain:acme.com`, public documents, and unrestricted documents. | @@ -215,21 +215,21 @@ Principals are lowercased, trimmed, and deduplicated on the way in. `__public__` Several emails in one list see the union of their views. An entry that is neither an email nor a recognized principal is kept as-is and matches nothing but public and unrestricted documents. A typo narrows results; it never widens them. If a caller sees less than you expect, check the principal spelling first. -## 3. Let connectors capture permissions +## 3. Let connectors capture ACL -For supported providers, HydraDB reads the source app's own permissions on every sync and applies them as ACLs, so you do not maintain a parallel permission model: +For supported providers, HydraDB captures the provider's ACL on every sync, so you do not maintain a second access model: -| Provider | What is captured | +| Provider | ACL HydraDB captures | |---|---| | **Slack** | Public channels are visible workspace-wide; private channels only to their members, resolved to member emails. | -| **Google Drive** | Per-file sharing: user, group, domain, and public grants. Permission-only changes (a share with no edit to the file) are picked up through the Drive changes feed, which content sync alone cannot see. | +| **Google Drive** | Per-file sharing: user, group, domain, and public grants. ACL-only changes are picked up through the Drive changes feed, even when the file content does not change. | | **GitHub** | Repository visibility. Private repos additionally capture the collaborator list when every collaborator has a visible public email; otherwise your resource rule governs. | -| **Confluence** | Space-level view permissions, with groups expanded to member emails, plus per-page view restrictions. | +| **Confluence** | Space-level view ACLs, with groups expanded to member emails, plus per-page view restrictions. | | **Jira** | Who holds Browse access per project, plus per-issue security levels. | -Capture is also built for GitLab, Linear, Dropbox, Zendesk, PagerDuty, Typeform, Attio, LaunchDarkly, ServiceNow, Microsoft Teams, and Outlook, and is switched on per provider. The [provider catalog](/api-reference/v2/endpoint/list-connector-providers) reports capture support in `rbac_support` and summarizes it in `rbac_description`. Check [Get Connector Status](/api-reference/v2/endpoint/get-connector-status) for an `acl_warning` after the first sync. For any other provider, [set your own rule on the resource](#set-your-own-rule-on-a-resource). +Capture is also built for GitLab, Linear, Dropbox, Zendesk, PagerDuty, Typeform, Attio, LaunchDarkly, ServiceNow, Microsoft Teams, and Outlook, and is switched on per provider. The [provider catalog](/api-reference/v2/endpoint/list-connector-providers) reports capture support in `acl_supported` and summarizes it in `acl_description`. Check [Get Connector Status](/api-reference/v2/endpoint/get-connector-status) for an `acl_warning` after the first sync. For any other provider, [set your own rule on the resource](#set-your-own-rule-on-a-resource). -By default, captured permissions are not enforced automatically on reads. A workspace owner can enable per-connector enforcement with `follow_source_permissions`, which is available only when the provider supports `rbac_support`. With enforcement enabled, the authenticated caller replaces a request's `acl` for content from that connector; an `acl` supplied on the request still scopes content from non-enforced connectors. See [Permissions on synced content](/essentials/v2/connectors#enforce-source-permissions-as-the-caller) for the identity rules and the machine-readable warning returned when an `acl` is overridden. +By default, captured ACLs are not enforced automatically on reads. A workspace owner can enable per-connector enforcement with `enforce_acl`, which is available only when the provider supports `acl_supported`. With enforcement enabled, the authenticated caller replaces a request's `acl` for content from that connector; an `acl` supplied on the request still scopes content from non-enforced connectors. See [ACL on synced content](/essentials/v2/connectors#enforce-acl) for the identity rules and the machine-readable warning returned when an `acl` is overridden. ### Set your own rule on a resource @@ -284,13 +284,13 @@ curl -X PATCH 'https://api.hydradb.com/connectors/conn_123/resources/C_LEADERSHI -### When the provider's permissions and your rule disagree +### When the provider ACL and your rule disagree -- **A per-document permission from the provider wins over everything:** a Drive file's own sharing decides that file. +- **A document ACL from the provider wins over everything:** a Drive file's own sharing decides that file. - **A provider verdict of "this resource is public" does not override a rule you set:** restricting a public channel is a deliberate act, and enabling capture never widens it back. - **Otherwise the provider's resource-level verdict wins over your rule:** the provider is the fresher source of truth. -If HydraDB cannot read a resource's permissions from the provider, a rule you set still applies. A resource with no rule of yours is readable by everyone until the next successful read. [Get Connector Status](/api-reference/v2/endpoint/get-connector-status) reports an `acl_warning` on the resource meanwhile, and a `page_acl_warning` when restrictions on some individual pages, for example in Confluence, could not be read. +If HydraDB cannot read a resource ACL from the provider, a rule you set still applies. A resource with no rule is readable by everyone until the next successful read. [Get Connector Status](/api-reference/v2/endpoint/get-connector-status) reports an `acl_warning` meanwhile, and a `page_acl_warning` when some page ACLs cannot be read. ## 4. Change or revoke access @@ -368,7 +368,7 @@ Check the principal forms on both sides. `group:slack:C0123` on the document onl ## Related -- [Connectors](/essentials/v2/connectors): syncing app data, per-resource ACL rules, and caller-bound source-permission enforcement +- [Connectors](/essentials/v2/connectors): syncing app data, per-resource ACL rules, and caller-bound ACL enforcement - [App Sources](/essentials/v2/app-sources): the ingest shape that carries `acl` - [Query](/essentials/v2/query): the `acl` field alongside every other retrieval parameter - [Metadata and Filters](/essentials/v2/metadata): narrow results by metadata diff --git a/essentials/v2/connectors.mdx b/essentials/v2/connectors.mdx index d641a187..b1bc36ba 100644 --- a/essentials/v2/connectors.mdx +++ b/essentials/v2/connectors.mdx @@ -14,7 +14,7 @@ In this guide: 3. [Change a connector after setup](#3-change-a-connector-after-setup): which call changes what. 4. [Custom ingestion instructions](#4-custom-ingestion-instructions): tell a connector how to read its documents. 5. [Filter on what HydraDB writes](#5-filter-on-what-hydradb-writes): the metadata every synced object carries. -6. [Permissions on synced content](#6-permissions-on-synced-content): the source app's permissions, your own rules, and optional caller-bound enforcement. +6. [ACL on synced content](#6-acl-on-synced-content): captured ACL, your own rules, and optional ACL enforcement. 7. [Connect several accounts of one provider](#7-connect-several-accounts-of-one-provider). 8. [Common mistakes](#common-mistakes) and [related pages](#related). @@ -277,12 +277,12 @@ curl -X POST 'https://api.hydradb.com/connectors/{id}/configure' \ | `credentials` | create | The provider's credentials, in the shape of its `credential_schema`. Credentials that do not match the schema are rejected with `422`. | | `custom_instructions` | create, configure | Guidance for how synced documents are interpreted, for the whole connector or for one resource. See [section 4](#4-custom-ingestion-instructions). | | `sync_interval_seconds` | create | How often scheduled syncs run. Omit it for the provider default, one hour for most providers. | -| `follow_source_permissions` | create, update | Whether reads from this connector always enforce the authenticated caller's source permissions. Optional and `false` by default. Only a workspace owner can set it, and enabling it requires a provider with `rbac_support`. See [enforced source permissions](#enforce-source-permissions-as-the-caller). | +| `enforce_acl` | create, update | Whether reads from this connector always enforce ACL for the authenticated caller. Optional and `false` by default. Only a workspace owner can set it, and enabling it requires a provider with `acl_supported`. See [ACL enforcement](#enforce-acl). | | `lookback_days` | configure | How much history the first sync fetches (default `30`). After that, each sync fetches only what is new. Above 30, some providers fetch the older history in the background and the response reports `backfill: true`. | | `resource_id`, `resource_type`, `name` | configure | The `id`, `resource_type`, and `name` of an entry from discover. Send all three every time you list a resource. | | `metadata` | configure | Fields merged into the database metadata of every object from this resource. Declare the ones you filter on in your database's [metadata schema](/essentials/v2/metadata). | | `additional_metadata` | configure | Free-form fields merged into the additional metadata of every object from this resource. No schema needed. | -| `acl` | configure | Who can read this resource's objects. Omitted means unrestricted. See [permissions](#6-permissions-on-synced-content). | +| `acl` | configure | Who can read this resource's objects. Omitted means unrestricted. See [ACL](#6-acl-on-synced-content). | @@ -510,16 +510,18 @@ To see which provider-native fields a connector writes, call [`GET /connectors/p + + -## 6. Permissions on synced content +## 6. ACL on synced content -For supported providers, HydraDB reads the source app's permissions on every sync and applies them as document access rules. Slack, Google Drive, GitHub, Confluence, and Jira are among the supported providers; [Access Control](/essentials/v2/access-control) lists what is captured for each. Capturing source permissions and enforcing them on every read are separate: the connector's `follow_source_permissions` setting controls enforcement. +For supported providers, HydraDB captures ACL from the provider on every sync. Slack, Google Drive, GitHub, Confluence, and Jira are among the supported providers; [Access Control](/essentials/v2/access-control) lists what is captured for each. Capture and enforcement are separate: the connector's `enforce_acl` setting controls ACL enforcement on reads. -By default, `follow_source_permissions` is `false`. Omitting it on create leaves the new connector unenforced, and existing connectors remain unenforced until an owner enables the setting. In this mode, access control remains opt-in on each request: send the caller's identity in `acl` to filter content, and a request without `acl` is not filtered by caller identity. This remains true for content from connectors whose enforcement is disabled, even when the same request also reads enforced connector content. MCP OAuth does not enforce caller identity for a non-enforced connector; send `acl` when that request needs caller filtering. +By default, `enforce_acl` is `false`. Omitting it on create leaves the new connector unenforced, and existing connectors remain unenforced until an owner enables the setting. In this mode, access control remains opt-in on each request: send the caller's identity in `acl` to filter content, and a request without `acl` is not filtered by caller identity. This remains true for content from connectors whose enforcement is disabled, even when the same request also reads enforced connector content. MCP OAuth does not enforce caller identity for a non-enforced connector; send `acl` when that request needs caller filtering. -### Enforce source permissions as the caller +### Enforce ACL -Set `follow_source_permissions` to `true` to make reads from this connector use the authenticated caller's identity against the source permissions HydraDB captured. The provider must report `rbac_support: true` in [List Connector Providers](/api-reference/v2/endpoint/list-connector-providers). The setting is optional on [`POST /connectors`](/api-reference/v2/endpoint/create-connector), defaults to `false`, and can be enabled or changed later with [`PATCH /connectors/{id}`](/api-reference/v2/endpoint/update-connector). In the dashboard, an owner can use the **Follow source permissions** control in the connector settings. A change takes effect on the next content request for already-synced documents and does not require re-ingestion. +Set `enforce_acl` to `true` to make reads from this connector use the authenticated caller's identity against the ACL HydraDB captured. The provider must report `acl_supported: true` in [List Connector Providers](/api-reference/v2/endpoint/list-connector-providers). The setting is optional on [`POST /connectors`](/api-reference/v2/endpoint/create-connector), defaults to `false`, and can be enabled or changed later with [`PATCH /connectors/{id}`](/api-reference/v2/endpoint/update-connector). In the dashboard, an owner can use the **Enforce ACL** control in the connector settings. A change takes effect on the next content request for already-synced documents and does not require re-ingestion. Only a workspace owner can set or change this setting. The API requires an owner in a signed-in dashboard session; API-key-authenticated requests can create a connector with the default `false` value, but cannot choose or change the setting. @@ -536,8 +538,8 @@ If a content-read request includes `acl`, HydraDB ignores it for content from co "meta": { "warnings": [ { - "code": "acl_overridden_by_connector_enforcement", - "message": "The caller-supplied acl was ignored for content from connectors that enforce source permissions." + "code": "acl_ignored_by_connector_enforcement", + "message": "This connector enforces ACL, so the request's acl was ignored." } ] } @@ -574,9 +576,9 @@ curl -X PATCH 'https://api.hydradb.com/connectors/{id}/resources/C_LEADERSHIP' \ -The change applies to already-synced documents on the next query, with no re-sync. Where HydraDB reads the provider's permissions, a per-document permission from the provider wins at the next sync; [Access Control](/essentials/v2/access-control) explains the full precedence. +The change applies to already-synced documents on the next query, with no re-sync. A document ACL from the provider wins at the next sync; [Access Control](/essentials/v2/access-control) explains the full precedence. -If HydraDB cannot read a resource's permissions from the provider, [Get Connector Status](/api-reference/v2/endpoint/get-connector-status) reports an `acl_warning` on it until the next successful read. Meanwhile your own rule on the resource still applies; a resource with no rule is readable by everyone. +If HydraDB cannot read a resource ACL from the provider, [Get Connector Status](/api-reference/v2/endpoint/get-connector-status) reports an `acl_warning` until the next successful read. Your own resource rule still applies; a resource with no rule is readable by everyone. diff --git a/essentials/v2/query.mdx b/essentials/v2/query.mdx index 70b9a044..a7f9aad6 100644 --- a/essentials/v2/query.mdx +++ b/essentials/v2/query.mdx @@ -223,7 +223,7 @@ Three fields bring in context beyond the passages that matched. All three are on ## 6. Query on behalf of a user -For directly ingested knowledge and content from connectors without source-permission enforcement, send the caller's email in `acl`, such as `"acl": ["grace@acme.com"]`, to filter results to documents that person may retrieve, plus public and unrestricted ones. Without `acl`, that content is not filtered by caller identity. For connectors with `follow_source_permissions` enabled, HydraDB uses the authenticated caller instead and ignores a request `acl` for that connector's content. API keys use the key creator's email; MCP OAuth and dashboard requests use the signed-in user. If you send `acl` while enforcement is enabled, a successful response includes one `meta.warnings` entry with code `acl_overridden_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control) and [Permissions on synced content](/essentials/v2/connectors#enforce-source-permissions-as-the-caller) for more. +For directly ingested knowledge and content from connectors without ACL enforcement, send the caller's email in `acl`, such as `"acl": ["grace@acme.com"]`, to filter results to documents that person may retrieve, plus public and unrestricted ones. Without `acl`, that content is not filtered by caller identity. For connectors with `enforce_acl` enabled, HydraDB uses the authenticated caller instead and ignores a request `acl` for that connector's content. API keys use the key creator's email; MCP OAuth and dashboard requests use the signed-in user. If you send `acl` while enforcement is enabled, a successful response includes one `meta.warnings` entry with code `acl_ignored_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control) and [ACL on synced content](/essentials/v2/connectors#enforce-acl) for more. ## Common mistakes From 36bfdc66785b82c75c94ef8b1ca40cc732c8004d Mon Sep 17 00:00:00 2001 From: Vorflux AI <249966464+vorflux[bot]@users.noreply.github.com> Date: Tue, 27 Oct 2026 07:39:11 +0000 Subject: [PATCH 5/8] docs: simplify connector ACL contract Signed-off-by: Vorflux AI <249966464+vorflux[bot]@users.noreply.github.com> --- .../v2/endpoint/create-connector.mdx | 2 +- api-reference/v2/endpoint/fetch-content.mdx | 2 +- .../v2/endpoint/list-connector-providers.mdx | 6 +-- api-reference/v2/endpoint/list-documents.mdx | 2 +- api-reference/v2/endpoint/query.mdx | 2 +- .../v2/endpoint/source-relations.mdx | 2 +- api-reference/v2/endpoint/subgraph.mdx | 2 +- .../v2/endpoint/update-connector.mdx | 10 ++--- api-reference/v2/openapi.json | 40 +++++-------------- essentials/v2/access-control.mdx | 4 +- essentials/v2/connectors.mdx | 8 +--- 11 files changed, 26 insertions(+), 54 deletions(-) diff --git a/api-reference/v2/endpoint/create-connector.mdx b/api-reference/v2/endpoint/create-connector.mdx index ba2263b5..9e121fcb 100644 --- a/api-reference/v2/endpoint/create-connector.mdx +++ b/api-reference/v2/endpoint/create-connector.mdx @@ -12,7 +12,7 @@ Optional settings you can also pass here, and change later with [Update Connecto - `custom_instructions`: guidance for how this connector's documents are interpreted and indexed. See [Custom Ingestion Instructions](/essentials/v2/connectors#custom-ingestion-instructions). - `sync_interval_seconds`: how often scheduled syncs run. Omit it for the provider default (one hour for most providers). -- `enforce_acl`: whether content reads always enforce ACL for the authenticated caller for this connector. It defaults to `false` when omitted. Only a workspace owner in a signed-in dashboard session can set it, and `true` requires the provider to report `acl_supported: true`. API-key-authenticated requests must omit this field. An owner can enable or change it later with [Update Connector](/api-reference/v2/endpoint/update-connector) or in the dashboard. See [ACL on synced content](/essentials/v2/connectors#enforce-acl) for how caller identity and request `acl` behave. +- `enforce_acl`: whether content reads always enforce ACL for the authenticated caller for this connector. It defaults to `false` when omitted. Only a workspace owner in a signed-in dashboard session can set it, and `true` requires the provider to report `rbac_support: true`. API-key-authenticated requests must omit this field. An owner can enable or change it later with [Update Connector](/api-reference/v2/endpoint/update-connector) or in the dashboard. See [ACL on synced content](/essentials/v2/connectors#enforce-acl) for how caller identity and request `acl` behave. diff --git a/api-reference/v2/endpoint/fetch-content.mdx b/api-reference/v2/endpoint/fetch-content.mdx index 587279a4..e1107486 100644 --- a/api-reference/v2/endpoint/fetch-content.mdx +++ b/api-reference/v2/endpoint/fetch-content.mdx @@ -49,7 +49,7 @@ curl -G 'https://api.hydradb.com/context/inspect' \ | | Collection scope. If omitted, the default collection is used. | | | What to return. See [Fetch modes](#fetch-modes). (default=`"both"`) | | | TTL of the presigned URL (when `mode` includes `url`). Range `60` to `604800` (7 days). (default=`3600`) | -| | Principals to answer as for directly ingested knowledge and content from connectors without ACL enforcement. A source they cannot see returns the same `404` as a missing one. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values; if `acl` is overridden, the response includes one `meta.warnings` entry with code `acl_ignored_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control). | +| | Principals to answer as (document ACLs). A source they cannot see returns the same `404` as a missing one. Repeat or comma-separate values. Omit for no caller-supplied ACL filtering. For enforced connectors, the authenticated caller is used instead; see [ACL enforcement](/essentials/v2/connectors#enforce-acl). | ## Fetch modes diff --git a/api-reference/v2/endpoint/list-connector-providers.mdx b/api-reference/v2/endpoint/list-connector-providers.mdx index b3790b64..ca6ea654 100644 --- a/api-reference/v2/endpoint/list-connector-providers.mdx +++ b/api-reference/v2/endpoint/list-connector-providers.mdx @@ -53,8 +53,8 @@ TypeScript SDK 2.1.7 requires the explicit authorization header for this method. "supported": true, "moveit_support": false, "webhook_support": false, - "acl_supported": true, - "acl_description": "Captures channel-level access: public channels are visible to the whole workspace, private channels only to their members.", + "rbac_support": true, + "rbac_description": "Captures channel-level access: public channels are visible to the whole workspace, private channels only to their members.", "is_alpha": false, "is_beta": false, "rank": 1 @@ -96,7 +96,7 @@ TypeScript SDK 2.1.7 requires the explicit authorization header for this method. Only providers you can connect are listed, so `supported` is always `true`. `webhook_support` is `true` for providers whose data arrives by webhook instead of scheduled syncs. `rank` is `null` for providers without a display position; they are listed last, alphabetically. -`acl_supported` indicates whether the provider captures ACL as document access rules. When it is `true`, `acl_description` summarizes the captured ACL. `enforce_acl` can only be enabled for a connector when its provider reports `acl_supported: true`; see [ACL on synced content](/essentials/v2/connectors#enforce-acl). +`rbac_support` indicates whether the provider captures ACL as document access rules. When it is `true`, `rbac_description` summarizes the captured ACL. `enforce_acl` can only be enabled for a connector when its provider reports `rbac_support: true`; see [ACL on synced content](/essentials/v2/connectors#enforce-acl). ## One provider diff --git a/api-reference/v2/endpoint/list-documents.mdx b/api-reference/v2/endpoint/list-documents.mdx index 6811c179..5f9ef6dc 100644 --- a/api-reference/v2/endpoint/list-documents.mdx +++ b/api-reference/v2/endpoint/list-documents.mdx @@ -76,7 +76,7 @@ curl -X POST 'https://api.hydradb.com/context/list' \ | | Items per page, from `1` to `100`. (default=`50`) | | | Structured exact-match filters. See [Filters](#filters). (default=`null`) | | | Field projection. Only the listed fields plus `id`, `database`, `collection` are populated. Only applies to `type=knowledge`. (default=`null`, all fields) | -| | Principals to list as for directly ingested knowledge and knowledge from connectors without ACL enforcement. Enforced connector content uses the authenticated caller instead. If supplied `acl` is overridden, the response includes one `meta.warnings` entry with code `acl_ignored_by_connector_enforcement`. Omitted, `[]`, or `["*"]` disables caller-supplied filtering outside enforced connectors. Ignored for `type=memory`. See [Access Control](/essentials/v2/access-control). | +| | Principals to list as (document ACLs). Omitted, `[]`, or `["*"]` disables caller-supplied filtering. Ignored for `type=memory`. For enforced connectors, the authenticated caller is used instead; see [ACL enforcement](/essentials/v2/connectors#enforce-acl). | ### Filters diff --git a/api-reference/v2/endpoint/query.mdx b/api-reference/v2/endpoint/query.mdx index b7bc7ce4..acd4fcec 100644 --- a/api-reference/v2/endpoint/query.mdx +++ b/api-reference/v2/endpoint/query.mdx @@ -316,7 +316,7 @@ result = client.query( | | Multi-collection scope. Send a list of collection IDs for equal weighting, or an object mapping collection ID to a positive relative weight (at most one decimal place, e.g. `{"finance": 1.5, "legal": 0.8}`) to bias ranking. Up to 100 collections. Do not combine with `collection`. | | | Query terms or natural-language question. Cannot be empty. Maximum 5,000 words. | | | Exact source titles, matched case-insensitively. Matches any listed title, then intersects with `ids` if both are sent. | -| | Caller identities used to filter directly ingested knowledge and content from connectors without ACL enforcement. Omitting `acl`, sending `[]`, or sending `["*"]` disables this caller-supplied filtering. For enforced connectors, HydraDB uses the authenticated caller instead and ignores this field for their content. If you send `acl` while enforcement is enabled, a successful response includes one `meta.warnings` entry with code `acl_ignored_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control) and [ACL on synced content](/essentials/v2/connectors#enforce-acl). | +| | Caller identities used to filter document ACLs. Omitting `acl`, sending `[]`, or sending `["*"]` disables caller-supplied filtering. For enforced connectors, the authenticated caller is used instead; see [ACL enforcement](/essentials/v2/connectors#enforce-acl). | | | Omit for the result object with `llm_prompt`. `"structured"` leaves out the prompt string. `"markdown"` returns the prompt string directly as `data`. | | | What to query. `"all"` runs knowledge and memory in parallel over the same scope and merges by `relevancy_score`. (default=`"knowledge"`) | | | Retrieval method. See [Query methods](#decision-matrix). (default=`"hybrid"`) | diff --git a/api-reference/v2/endpoint/source-relations.mdx b/api-reference/v2/endpoint/source-relations.mdx index de50728f..63b9a6df 100644 --- a/api-reference/v2/endpoint/source-relations.mdx +++ b/api-reference/v2/endpoint/source-relations.mdx @@ -49,7 +49,7 @@ curl -G 'https://api.hydradb.com/context/relations' \ | | Collection scope. If omitted, the default collection is used. | | | Maximum relation groups to return. Range `1` to `10000`. (default=`5000`) | | | Opaque pagination cursor from a previous response's `next_cursor`. (default=`null`) | -| | Principals to answer as for directly ingested knowledge and content from connectors without ACL enforcement. Only relations from sources those principals may see are returned. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values; if `acl` is overridden, the response includes one `meta.warnings` entry with code `acl_ignored_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control). | +| | Principals to answer as (document ACLs). Only relations from sources those principals may see are returned. Repeat or comma-separate values. Omit for no caller-supplied ACL filtering. For enforced connectors, the authenticated caller is used instead; see [ACL enforcement](/essentials/v2/connectors#enforce-acl). | diff --git a/api-reference/v2/endpoint/subgraph.mdx b/api-reference/v2/endpoint/subgraph.mdx index cf1b1ca4..0449c790 100644 --- a/api-reference/v2/endpoint/subgraph.mdx +++ b/api-reference/v2/endpoint/subgraph.mdx @@ -56,7 +56,7 @@ curl -G 'https://api.hydradb.com/context/slack_C0BE77_1788320073/subgraph' \ | | Which graph the `id` belongs to. The two graphs are completely separate. (default=`"knowledge"`) | | | Maximum traversal depth in hops. Range `1` to `10`. (default=`5`) | | | Maximum number of members returned. Range `1` to `1000`. When this clips the traversal, `is_truncated` is `true`. (default=`200`) | -| | Principals to answer as for directly ingested knowledge and content from connectors without ACL enforcement. The subgraph then contains only items those principals may see, filtered at every hop. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values; if `acl` is overridden, the response includes one `meta.warnings` entry with code `acl_ignored_by_connector_enforcement`. See [Access Control](/essentials/v2/access-control). | +| | Principals to answer as (document ACLs). Only items those principals may see are returned, filtered at every hop. Repeat or comma-separate values. Omit for no caller-supplied ACL filtering. For enforced connectors, the authenticated caller is used instead; see [ACL enforcement](/essentials/v2/connectors#enforce-acl). | ## How items connect diff --git a/api-reference/v2/endpoint/update-connector.mdx b/api-reference/v2/endpoint/update-connector.mdx index 141ca447..f3e969c9 100644 --- a/api-reference/v2/endpoint/update-connector.mdx +++ b/api-reference/v2/endpoint/update-connector.mdx @@ -12,9 +12,9 @@ Update a connector's instructions, sync interval, credentials, or ACL enforcemen - `custom_instructions` applies to resources without their own instructions. Maximum 4,000 characters. Send `""` to clear it. Changes affect future syncs. See [Custom Ingestion Instructions](/essentials/v2/connectors#custom-ingestion-instructions). - `sync_interval_seconds` reschedules the next sync. Stay within the returned `min_sync_interval_seconds` and `max_sync_interval_seconds`, or send `0` for the provider default. - `credentials` reconnects the existing connector. Send the provider's complete credential set. Resources and saved sync positions are preserved. -- `enforce_acl` enables or disables caller-bound enforcement of this connector's captured ACL. Existing connectors remain `false` until an owner enables it. Send `true` to enforce captured ACL on every content read, or `false` to return to opt-in request `acl` filtering. Omit it to keep the current value. The change takes effect on the next content request for already-synced documents and does not require re-ingestion. Only a workspace owner in a signed-in dashboard session can set it; `true` requires the provider to report `acl_supported: true`. API-key-authenticated requests cannot set it. See [ACL on synced content](/essentials/v2/connectors#enforce-acl) and [Access Control](/essentials/v2/access-control). +- `enforce_acl` enables or disables caller-bound enforcement of this connector's captured ACL. Existing connectors remain `false` until an owner enables it. Send `true` to enforce captured ACL on every content read, or `false` to return to opt-in request `acl` filtering. Omit it to keep the current value. The change takes effect on the next content request for already-synced documents and does not require re-ingestion. Only a workspace owner in a signed-in dashboard session can set it; `true` requires the provider to report `rbac_support: true`. API-key-authenticated requests cannot set it. See [ACL on synced content](/essentials/v2/connectors#enforce-acl) and [Access Control](/essentials/v2/access-control). -To enable enforcement later, send this field in a separate PATCH request, or use **Enforce ACL** in the dashboard's connector settings: +To enable enforcement later, send this field in a PATCH request, or use **Enforce ACL** in the dashboard's connector settings: ```json { @@ -22,8 +22,6 @@ To enable enforcement later, send this field in a separate PATCH request, or use } ``` -Do not combine `enforce_acl` and `credentials` in the same PATCH request. Send them in separate requests. - Only `custom_instructions`, `sync_interval_seconds`, `credentials`, and `enforce_acl` can be updated. A connector's `name`, `database`, `collection` and `provider_account_scope` cannot be changed after creation. Omit them from the request; unsupported fields can cause a `400` response. @@ -82,12 +80,10 @@ curl -X PATCH 'https://api.hydradb.com/connectors/{id}' \ ## Errors -- `400`: the request includes an unsupported field, `enforce_acl` is combined with `credentials`, the provider does not report `acl_supported` for `enforce_acl: true`, `custom_instructions` is over 4,000 characters, or `sync_interval_seconds` is outside the provider's range. Nothing is changed. +- `400`: the request includes an unsupported field, the provider does not report `rbac_support` for `enforce_acl: true`, `custom_instructions` is over 4,000 characters, or `sync_interval_seconds` is outside the provider's range. Nothing is changed. - `403`: the request tries to set `enforce_acl` without a workspace owner's signed-in dashboard session. - `404`: no connector with this id in your organization. -- `409`: another update changed ACL enforcement at the same time. Reload the connector and retry. - `422`: `credentials` does not match the provider's `credential_schema`. -- `503`: the provider capability catalog is unavailable. Retry the request.
diff --git a/api-reference/v2/openapi.json b/api-reference/v2/openapi.json index 53ca8ba8..d7416814 100644 --- a/api-reference/v2/openapi.json +++ b/api-reference/v2/openapi.json @@ -2980,11 +2980,11 @@ "null" ] }, - "acl_description": { - "description": "One-line summary of the provider ACL captured as document access rules. Present when `acl_supported` is true.", + "rbac_description": { + "description": "One-line summary of the provider ACL captured as document access rules. Present when `rbac_support` is true.", "type": "string" }, - "acl_supported": { + "rbac_support": { "description": "True when the provider captures ACL as document access rules. Connector ACL enforcement can be enabled only when this is true.", "example": true, "type": "boolean" @@ -3309,7 +3309,7 @@ "type": "string" }, "enforce_acl": { - "description": "Optional owner-only setting; defaults to false. True requires provider `acl_supported` and enables caller-bound reads; false keeps request `acl` as an opt-in filter.", + "description": "Optional owner-only setting; defaults to false. True requires provider `rbac_support` and enables caller-bound reads; false keeps request `acl` as an opt-in filter.", "example": true, "type": "boolean" }, @@ -3920,7 +3920,7 @@ "type": "string" }, "enforce_acl": { - "description": "Set whether the connector enforces ACL. Omit to keep the current value; only a workspace owner may set it. True requires provider catalog `acl_supported`.", + "description": "Set whether the connector enforces ACL. Omit to keep the current value; only a workspace owner may set it. True requires provider catalog `rbac_support`.", "example": true, "type": "boolean" }, @@ -4386,10 +4386,10 @@ "is_beta": true, "moveit_support": true, "provider": "slack", - "acl_supported": true, + "rbac_support": true, "supported": true, "webhook_support": true, - "acl_description": "Captures channel-level access: public channels are visible to the workspace, private channels only to their members." + "rbac_description": "Captures channel-level access: public channels are visible to the workspace, private channels only to their members." } ], "items": { @@ -8078,7 +8078,7 @@ "x-fern-sdk-method-name": "list" }, "post": { - "description": "Create a connector for a provider and store its credentials. `enforce_acl` defaults to false when omitted, so writers may create connectors without choosing the setting. Only a workspace owner in a human dashboard session may explicitly set it, and true is accepted only when the provider catalog reports acl_supported. When true, content reads always use the authenticated caller; when false, request `acl` remains an opt-in filter.", + "description": "Create a connector for a provider and store its credentials. `enforce_acl` defaults to false when omitted, so writers may create connectors without choosing the setting. Only a workspace owner in a human dashboard session may explicitly set it, and true is accepted only when the provider catalog reports rbac_support. When true, content reads always use the authenticated caller; when false, request `acl` remains an opt-in filter.", "requestBody": { "content": { "application/json": { @@ -8157,7 +8157,7 @@ }, "/connectors/providers": { "get": { - "description": "Lists the providers you can connect, including whether ACL capture is supported (`acl_supported`) and its summary (`acl_description`). With `id`, describes one provider: its searchable object types and fields (with `filter_key`), `credential_schema`, and `setup_guide` when needed.", + "description": "Lists the providers you can connect, including whether ACL capture is supported (`rbac_support`) and its summary (`rbac_description`). With `id`, describes one provider: its searchable object types and fields (with `filter_key`), `credential_schema`, and `setup_guide` when needed.", "parameters": [ { "description": "Provider name (e.g. slack, gmail). Omit to list all.", @@ -8330,7 +8330,7 @@ "x-fern-sdk-method-name": "get" }, "patch": { - "description": "Update the supplied connector settings. Use `credentials` to reconnect, `sync_interval_seconds` to change cadence, `custom_instructions` to change ingestion instructions, or `enforce_acl` to set the owner-only enforcement mode. True requires provider catalog `acl_supported`; when enabled, content reads use the authenticated caller, while false keeps request `acl` as an opt-in filter.", + "description": "Update the supplied connector settings. Use `credentials` to reconnect, `sync_interval_seconds` to change cadence, `custom_instructions` to change ingestion instructions, or `enforce_acl` to set the owner-only enforcement mode. True requires provider catalog `rbac_support`; when enabled, content reads use the authenticated caller, while false keeps request `acl` as an opt-in filter.", "parameters": [ { "description": "Connector ID", @@ -8395,16 +8395,6 @@ }, "description": "Not Found" }, - "409": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/handler.ErrorResponse" - } - } - }, - "description": "The ACL enforcement revision changed after the connector was loaded; reload and retry. If the connector was deleted, the handler returns 404." - }, "500": { "content": { "application/json": { @@ -8414,16 +8404,6 @@ } }, "description": "Internal Server Error" - }, - "503": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/handler.ErrorResponse" - } - } - }, - "description": "The provider capability catalog is unavailable; retry the request." } }, "security": [ diff --git a/essentials/v2/access-control.mdx b/essentials/v2/access-control.mdx index cdf57e64..211f18a4 100644 --- a/essentials/v2/access-control.mdx +++ b/essentials/v2/access-control.mdx @@ -227,9 +227,9 @@ For supported providers, HydraDB captures the provider's ACL on every sync, so y | **Confluence** | Space-level view ACLs, with groups expanded to member emails, plus per-page view restrictions. | | **Jira** | Who holds Browse access per project, plus per-issue security levels. | -Capture is also built for GitLab, Linear, Dropbox, Zendesk, PagerDuty, Typeform, Attio, LaunchDarkly, ServiceNow, Microsoft Teams, and Outlook, and is switched on per provider. The [provider catalog](/api-reference/v2/endpoint/list-connector-providers) reports capture support in `acl_supported` and summarizes it in `acl_description`. Check [Get Connector Status](/api-reference/v2/endpoint/get-connector-status) for an `acl_warning` after the first sync. For any other provider, [set your own rule on the resource](#set-your-own-rule-on-a-resource). +Capture is also built for GitLab, Linear, Dropbox, Zendesk, PagerDuty, Typeform, Attio, LaunchDarkly, ServiceNow, Microsoft Teams, and Outlook, and is switched on per provider. The [provider catalog](/api-reference/v2/endpoint/list-connector-providers) reports capture support in `rbac_support` and summarizes it in `rbac_description`. Check [Get Connector Status](/api-reference/v2/endpoint/get-connector-status) for an `acl_warning` after the first sync. For any other provider, [set your own rule on the resource](#set-your-own-rule-on-a-resource). -By default, captured ACLs are not enforced automatically on reads. A workspace owner can enable per-connector enforcement with `enforce_acl`, which is available only when the provider supports `acl_supported`. With enforcement enabled, the authenticated caller replaces a request's `acl` for content from that connector; an `acl` supplied on the request still scopes content from non-enforced connectors. See [ACL on synced content](/essentials/v2/connectors#enforce-acl) for the identity rules and the machine-readable warning returned when an `acl` is overridden. +By default, captured ACLs are not enforced automatically on reads. A workspace owner can enable per-connector enforcement with `enforce_acl`, which is available only when the provider supports `rbac_support`. With enforcement enabled, the authenticated caller replaces a request's `acl` for content from that connector; an `acl` supplied on the request still scopes content from non-enforced connectors. See [ACL on synced content](/essentials/v2/connectors#enforce-acl) for the identity rules and the machine-readable warning returned when an `acl` is overridden. ### Set your own rule on a resource diff --git a/essentials/v2/connectors.mdx b/essentials/v2/connectors.mdx index b1bc36ba..6cae1014 100644 --- a/essentials/v2/connectors.mdx +++ b/essentials/v2/connectors.mdx @@ -277,7 +277,7 @@ curl -X POST 'https://api.hydradb.com/connectors/{id}/configure' \ | `credentials` | create | The provider's credentials, in the shape of its `credential_schema`. Credentials that do not match the schema are rejected with `422`. | | `custom_instructions` | create, configure | Guidance for how synced documents are interpreted, for the whole connector or for one resource. See [section 4](#4-custom-ingestion-instructions). | | `sync_interval_seconds` | create | How often scheduled syncs run. Omit it for the provider default, one hour for most providers. | -| `enforce_acl` | create, update | Whether reads from this connector always enforce ACL for the authenticated caller. Optional and `false` by default. Only a workspace owner can set it, and enabling it requires a provider with `acl_supported`. See [ACL enforcement](#enforce-acl). | +| `enforce_acl` | create, update | Whether reads from this connector always enforce ACL for the authenticated caller. Optional and `false` by default. Only a workspace owner can set it, and enabling it requires a provider with `rbac_support`. See [ACL enforcement](#enforce-acl). | | `lookback_days` | configure | How much history the first sync fetches (default `30`). After that, each sync fetches only what is new. Above 30, some providers fetch the older history in the background and the response reports `backfill: true`. | | `resource_id`, `resource_type`, `name` | configure | The `id`, `resource_type`, and `name` of an entry from discover. Send all three every time you list a resource. | | `metadata` | configure | Fields merged into the database metadata of every object from this resource. Declare the ones you filter on in your database's [metadata schema](/essentials/v2/metadata). | @@ -508,10 +508,6 @@ Filter on `resource_id` the same way to scope to one channel, repository, or tab To see which provider-native fields a connector writes, call [`GET /connectors/providers?id={provider}`](/api-reference/v2/endpoint/list-connector-providers). Its `filterable_fields` each carry the `filter_key` to use in `metadata_filters`. Its `searchable_fields` are combined into each document's searchable text, so you search them together, not one at a time. - - - - ## 6. ACL on synced content @@ -521,7 +517,7 @@ By default, `enforce_acl` is `false`. Omitting it on create leaves the new conne ### Enforce ACL -Set `enforce_acl` to `true` to make reads from this connector use the authenticated caller's identity against the ACL HydraDB captured. The provider must report `acl_supported: true` in [List Connector Providers](/api-reference/v2/endpoint/list-connector-providers). The setting is optional on [`POST /connectors`](/api-reference/v2/endpoint/create-connector), defaults to `false`, and can be enabled or changed later with [`PATCH /connectors/{id}`](/api-reference/v2/endpoint/update-connector). In the dashboard, an owner can use the **Enforce ACL** control in the connector settings. A change takes effect on the next content request for already-synced documents and does not require re-ingestion. +Set `enforce_acl` to `true` to make reads from this connector use the authenticated caller's identity against the ACL HydraDB captured. The provider must report `rbac_support: true` in [List Connector Providers](/api-reference/v2/endpoint/list-connector-providers). The setting is optional on [`POST /connectors`](/api-reference/v2/endpoint/create-connector), defaults to `false`, and can be enabled or changed later with [`PATCH /connectors/{id}`](/api-reference/v2/endpoint/update-connector). In the dashboard, an owner can use the **Enforce ACL** control in the connector settings. A change takes effect on the next content request for already-synced documents and does not require re-ingestion. Only a workspace owner can set or change this setting. The API requires an owner in a signed-in dashboard session; API-key-authenticated requests can create a connector with the default `false` value, but cannot choose or change the setting. From 212f85ded422bceba4dc2a8169b10a263107acf9 Mon Sep 17 00:00:00 2001 From: Vorflux AI <249966464+vorflux[bot]@users.noreply.github.com> Date: Tue, 27 Oct 2026 07:41:35 +0000 Subject: [PATCH 6/8] docs: correct provider ACL field names Signed-off-by: Vorflux AI <249966464+vorflux[bot]@users.noreply.github.com> --- .../v2/endpoint/create-connector.mdx | 2 +- .../v2/endpoint/list-connector-providers.mdx | 6 +++--- .../v2/endpoint/update-connector.mdx | 4 ++-- api-reference/v2/openapi.json | 20 +++++++++---------- essentials/v2/access-control.mdx | 4 ++-- essentials/v2/connectors.mdx | 4 ++-- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/api-reference/v2/endpoint/create-connector.mdx b/api-reference/v2/endpoint/create-connector.mdx index 9e121fcb..ba2263b5 100644 --- a/api-reference/v2/endpoint/create-connector.mdx +++ b/api-reference/v2/endpoint/create-connector.mdx @@ -12,7 +12,7 @@ Optional settings you can also pass here, and change later with [Update Connecto - `custom_instructions`: guidance for how this connector's documents are interpreted and indexed. See [Custom Ingestion Instructions](/essentials/v2/connectors#custom-ingestion-instructions). - `sync_interval_seconds`: how often scheduled syncs run. Omit it for the provider default (one hour for most providers). -- `enforce_acl`: whether content reads always enforce ACL for the authenticated caller for this connector. It defaults to `false` when omitted. Only a workspace owner in a signed-in dashboard session can set it, and `true` requires the provider to report `rbac_support: true`. API-key-authenticated requests must omit this field. An owner can enable or change it later with [Update Connector](/api-reference/v2/endpoint/update-connector) or in the dashboard. See [ACL on synced content](/essentials/v2/connectors#enforce-acl) for how caller identity and request `acl` behave. +- `enforce_acl`: whether content reads always enforce ACL for the authenticated caller for this connector. It defaults to `false` when omitted. Only a workspace owner in a signed-in dashboard session can set it, and `true` requires the provider to report `acl_supported: true`. API-key-authenticated requests must omit this field. An owner can enable or change it later with [Update Connector](/api-reference/v2/endpoint/update-connector) or in the dashboard. See [ACL on synced content](/essentials/v2/connectors#enforce-acl) for how caller identity and request `acl` behave. diff --git a/api-reference/v2/endpoint/list-connector-providers.mdx b/api-reference/v2/endpoint/list-connector-providers.mdx index ca6ea654..b3790b64 100644 --- a/api-reference/v2/endpoint/list-connector-providers.mdx +++ b/api-reference/v2/endpoint/list-connector-providers.mdx @@ -53,8 +53,8 @@ TypeScript SDK 2.1.7 requires the explicit authorization header for this method. "supported": true, "moveit_support": false, "webhook_support": false, - "rbac_support": true, - "rbac_description": "Captures channel-level access: public channels are visible to the whole workspace, private channels only to their members.", + "acl_supported": true, + "acl_description": "Captures channel-level access: public channels are visible to the whole workspace, private channels only to their members.", "is_alpha": false, "is_beta": false, "rank": 1 @@ -96,7 +96,7 @@ TypeScript SDK 2.1.7 requires the explicit authorization header for this method. Only providers you can connect are listed, so `supported` is always `true`. `webhook_support` is `true` for providers whose data arrives by webhook instead of scheduled syncs. `rank` is `null` for providers without a display position; they are listed last, alphabetically. -`rbac_support` indicates whether the provider captures ACL as document access rules. When it is `true`, `rbac_description` summarizes the captured ACL. `enforce_acl` can only be enabled for a connector when its provider reports `rbac_support: true`; see [ACL on synced content](/essentials/v2/connectors#enforce-acl). +`acl_supported` indicates whether the provider captures ACL as document access rules. When it is `true`, `acl_description` summarizes the captured ACL. `enforce_acl` can only be enabled for a connector when its provider reports `acl_supported: true`; see [ACL on synced content](/essentials/v2/connectors#enforce-acl). ## One provider diff --git a/api-reference/v2/endpoint/update-connector.mdx b/api-reference/v2/endpoint/update-connector.mdx index f3e969c9..2547be17 100644 --- a/api-reference/v2/endpoint/update-connector.mdx +++ b/api-reference/v2/endpoint/update-connector.mdx @@ -12,7 +12,7 @@ Update a connector's instructions, sync interval, credentials, or ACL enforcemen - `custom_instructions` applies to resources without their own instructions. Maximum 4,000 characters. Send `""` to clear it. Changes affect future syncs. See [Custom Ingestion Instructions](/essentials/v2/connectors#custom-ingestion-instructions). - `sync_interval_seconds` reschedules the next sync. Stay within the returned `min_sync_interval_seconds` and `max_sync_interval_seconds`, or send `0` for the provider default. - `credentials` reconnects the existing connector. Send the provider's complete credential set. Resources and saved sync positions are preserved. -- `enforce_acl` enables or disables caller-bound enforcement of this connector's captured ACL. Existing connectors remain `false` until an owner enables it. Send `true` to enforce captured ACL on every content read, or `false` to return to opt-in request `acl` filtering. Omit it to keep the current value. The change takes effect on the next content request for already-synced documents and does not require re-ingestion. Only a workspace owner in a signed-in dashboard session can set it; `true` requires the provider to report `rbac_support: true`. API-key-authenticated requests cannot set it. See [ACL on synced content](/essentials/v2/connectors#enforce-acl) and [Access Control](/essentials/v2/access-control). +- `enforce_acl` enables or disables caller-bound enforcement of this connector's captured ACL. Existing connectors remain `false` until an owner enables it. Send `true` to enforce captured ACL on every content read, or `false` to return to opt-in request `acl` filtering. Omit it to keep the current value. The change takes effect on the next content request for already-synced documents and does not require re-ingestion. Only a workspace owner in a signed-in dashboard session can set it; `true` requires the provider to report `acl_supported: true`. API-key-authenticated requests cannot set it. See [ACL on synced content](/essentials/v2/connectors#enforce-acl) and [Access Control](/essentials/v2/access-control). To enable enforcement later, send this field in a PATCH request, or use **Enforce ACL** in the dashboard's connector settings: @@ -80,7 +80,7 @@ curl -X PATCH 'https://api.hydradb.com/connectors/{id}' \ ## Errors -- `400`: the request includes an unsupported field, the provider does not report `rbac_support` for `enforce_acl: true`, `custom_instructions` is over 4,000 characters, or `sync_interval_seconds` is outside the provider's range. Nothing is changed. +- `400`: the request includes an unsupported field, the provider does not report `acl_supported` for `enforce_acl: true`, `custom_instructions` is over 4,000 characters, or `sync_interval_seconds` is outside the provider's range. Nothing is changed. - `403`: the request tries to set `enforce_acl` without a workspace owner's signed-in dashboard session. - `404`: no connector with this id in your organization. - `422`: `credentials` does not match the provider's `credential_schema`. diff --git a/api-reference/v2/openapi.json b/api-reference/v2/openapi.json index d7416814..baee3ecd 100644 --- a/api-reference/v2/openapi.json +++ b/api-reference/v2/openapi.json @@ -2980,11 +2980,11 @@ "null" ] }, - "rbac_description": { - "description": "One-line summary of the provider ACL captured as document access rules. Present when `rbac_support` is true.", + "acl_description": { + "description": "One-line summary of the provider ACL captured as document access rules. Present when `acl_supported` is true.", "type": "string" }, - "rbac_support": { + "acl_supported": { "description": "True when the provider captures ACL as document access rules. Connector ACL enforcement can be enabled only when this is true.", "example": true, "type": "boolean" @@ -3309,7 +3309,7 @@ "type": "string" }, "enforce_acl": { - "description": "Optional owner-only setting; defaults to false. True requires provider `rbac_support` and enables caller-bound reads; false keeps request `acl` as an opt-in filter.", + "description": "Optional owner-only setting; defaults to false. True requires provider `acl_supported` and enables caller-bound reads; false keeps request `acl` as an opt-in filter.", "example": true, "type": "boolean" }, @@ -3920,7 +3920,7 @@ "type": "string" }, "enforce_acl": { - "description": "Set whether the connector enforces ACL. Omit to keep the current value; only a workspace owner may set it. True requires provider catalog `rbac_support`.", + "description": "Set whether the connector enforces ACL. Omit to keep the current value; only a workspace owner may set it. True requires provider catalog `acl_supported`.", "example": true, "type": "boolean" }, @@ -4386,10 +4386,10 @@ "is_beta": true, "moveit_support": true, "provider": "slack", - "rbac_support": true, + "acl_supported": true, "supported": true, "webhook_support": true, - "rbac_description": "Captures channel-level access: public channels are visible to the workspace, private channels only to their members." + "acl_description": "Captures channel-level access: public channels are visible to the workspace, private channels only to their members." } ], "items": { @@ -8078,7 +8078,7 @@ "x-fern-sdk-method-name": "list" }, "post": { - "description": "Create a connector for a provider and store its credentials. `enforce_acl` defaults to false when omitted, so writers may create connectors without choosing the setting. Only a workspace owner in a human dashboard session may explicitly set it, and true is accepted only when the provider catalog reports rbac_support. When true, content reads always use the authenticated caller; when false, request `acl` remains an opt-in filter.", + "description": "Create a connector for a provider and store its credentials. `enforce_acl` defaults to false when omitted, so writers may create connectors without choosing the setting. Only a workspace owner in a human dashboard session may explicitly set it, and true is accepted only when the provider catalog reports acl_supported. When true, content reads always use the authenticated caller; when false, request `acl` remains an opt-in filter.", "requestBody": { "content": { "application/json": { @@ -8157,7 +8157,7 @@ }, "/connectors/providers": { "get": { - "description": "Lists the providers you can connect, including whether ACL capture is supported (`rbac_support`) and its summary (`rbac_description`). With `id`, describes one provider: its searchable object types and fields (with `filter_key`), `credential_schema`, and `setup_guide` when needed.", + "description": "Lists the providers you can connect, including whether ACL capture is supported (`acl_supported`) and its summary (`acl_description`). With `id`, describes one provider: its searchable object types and fields (with `filter_key`), `credential_schema`, and `setup_guide` when needed.", "parameters": [ { "description": "Provider name (e.g. slack, gmail). Omit to list all.", @@ -8330,7 +8330,7 @@ "x-fern-sdk-method-name": "get" }, "patch": { - "description": "Update the supplied connector settings. Use `credentials` to reconnect, `sync_interval_seconds` to change cadence, `custom_instructions` to change ingestion instructions, or `enforce_acl` to set the owner-only enforcement mode. True requires provider catalog `rbac_support`; when enabled, content reads use the authenticated caller, while false keeps request `acl` as an opt-in filter.", + "description": "Update the supplied connector settings. Use `credentials` to reconnect, `sync_interval_seconds` to change cadence, `custom_instructions` to change ingestion instructions, or `enforce_acl` to set the owner-only enforcement mode. True requires provider catalog `acl_supported`; when enabled, content reads use the authenticated caller, while false keeps request `acl` as an opt-in filter.", "parameters": [ { "description": "Connector ID", diff --git a/essentials/v2/access-control.mdx b/essentials/v2/access-control.mdx index 211f18a4..cdf57e64 100644 --- a/essentials/v2/access-control.mdx +++ b/essentials/v2/access-control.mdx @@ -227,9 +227,9 @@ For supported providers, HydraDB captures the provider's ACL on every sync, so y | **Confluence** | Space-level view ACLs, with groups expanded to member emails, plus per-page view restrictions. | | **Jira** | Who holds Browse access per project, plus per-issue security levels. | -Capture is also built for GitLab, Linear, Dropbox, Zendesk, PagerDuty, Typeform, Attio, LaunchDarkly, ServiceNow, Microsoft Teams, and Outlook, and is switched on per provider. The [provider catalog](/api-reference/v2/endpoint/list-connector-providers) reports capture support in `rbac_support` and summarizes it in `rbac_description`. Check [Get Connector Status](/api-reference/v2/endpoint/get-connector-status) for an `acl_warning` after the first sync. For any other provider, [set your own rule on the resource](#set-your-own-rule-on-a-resource). +Capture is also built for GitLab, Linear, Dropbox, Zendesk, PagerDuty, Typeform, Attio, LaunchDarkly, ServiceNow, Microsoft Teams, and Outlook, and is switched on per provider. The [provider catalog](/api-reference/v2/endpoint/list-connector-providers) reports capture support in `acl_supported` and summarizes it in `acl_description`. Check [Get Connector Status](/api-reference/v2/endpoint/get-connector-status) for an `acl_warning` after the first sync. For any other provider, [set your own rule on the resource](#set-your-own-rule-on-a-resource). -By default, captured ACLs are not enforced automatically on reads. A workspace owner can enable per-connector enforcement with `enforce_acl`, which is available only when the provider supports `rbac_support`. With enforcement enabled, the authenticated caller replaces a request's `acl` for content from that connector; an `acl` supplied on the request still scopes content from non-enforced connectors. See [ACL on synced content](/essentials/v2/connectors#enforce-acl) for the identity rules and the machine-readable warning returned when an `acl` is overridden. +By default, captured ACLs are not enforced automatically on reads. A workspace owner can enable per-connector enforcement with `enforce_acl`, which is available only when the provider supports `acl_supported`. With enforcement enabled, the authenticated caller replaces a request's `acl` for content from that connector; an `acl` supplied on the request still scopes content from non-enforced connectors. See [ACL on synced content](/essentials/v2/connectors#enforce-acl) for the identity rules and the machine-readable warning returned when an `acl` is overridden. ### Set your own rule on a resource diff --git a/essentials/v2/connectors.mdx b/essentials/v2/connectors.mdx index 6cae1014..407e6b3d 100644 --- a/essentials/v2/connectors.mdx +++ b/essentials/v2/connectors.mdx @@ -277,7 +277,7 @@ curl -X POST 'https://api.hydradb.com/connectors/{id}/configure' \ | `credentials` | create | The provider's credentials, in the shape of its `credential_schema`. Credentials that do not match the schema are rejected with `422`. | | `custom_instructions` | create, configure | Guidance for how synced documents are interpreted, for the whole connector or for one resource. See [section 4](#4-custom-ingestion-instructions). | | `sync_interval_seconds` | create | How often scheduled syncs run. Omit it for the provider default, one hour for most providers. | -| `enforce_acl` | create, update | Whether reads from this connector always enforce ACL for the authenticated caller. Optional and `false` by default. Only a workspace owner can set it, and enabling it requires a provider with `rbac_support`. See [ACL enforcement](#enforce-acl). | +| `enforce_acl` | create, update | Whether reads from this connector always enforce ACL for the authenticated caller. Optional and `false` by default. Only a workspace owner can set it, and enabling it requires a provider with `acl_supported`. See [ACL enforcement](#enforce-acl). | | `lookback_days` | configure | How much history the first sync fetches (default `30`). After that, each sync fetches only what is new. Above 30, some providers fetch the older history in the background and the response reports `backfill: true`. | | `resource_id`, `resource_type`, `name` | configure | The `id`, `resource_type`, and `name` of an entry from discover. Send all three every time you list a resource. | | `metadata` | configure | Fields merged into the database metadata of every object from this resource. Declare the ones you filter on in your database's [metadata schema](/essentials/v2/metadata). | @@ -517,7 +517,7 @@ By default, `enforce_acl` is `false`. Omitting it on create leaves the new conne ### Enforce ACL -Set `enforce_acl` to `true` to make reads from this connector use the authenticated caller's identity against the ACL HydraDB captured. The provider must report `rbac_support: true` in [List Connector Providers](/api-reference/v2/endpoint/list-connector-providers). The setting is optional on [`POST /connectors`](/api-reference/v2/endpoint/create-connector), defaults to `false`, and can be enabled or changed later with [`PATCH /connectors/{id}`](/api-reference/v2/endpoint/update-connector). In the dashboard, an owner can use the **Enforce ACL** control in the connector settings. A change takes effect on the next content request for already-synced documents and does not require re-ingestion. +Set `enforce_acl` to `true` to make reads from this connector use the authenticated caller's identity against the ACL HydraDB captured. The provider must report `acl_supported: true` in [List Connector Providers](/api-reference/v2/endpoint/list-connector-providers). The setting is optional on [`POST /connectors`](/api-reference/v2/endpoint/create-connector), defaults to `false`, and can be enabled or changed later with [`PATCH /connectors/{id}`](/api-reference/v2/endpoint/update-connector). In the dashboard, an owner can use the **Enforce ACL** control in the connector settings. A change takes effect on the next content request for already-synced documents and does not require re-ingestion. Only a workspace owner can set or change this setting. The API requires an owner in a signed-in dashboard session; API-key-authenticated requests can create a connector with the default `false` value, but cannot choose or change the setting. From 2ca136184b4bfeb3fec60b787ffbdda160091e5a Mon Sep 17 00:00:00 2001 From: SohamRatnaparkhi <92905626+SohamRatnaparkhi@users.noreply.github.com> Date: Tue, 27 Oct 2026 14:02:08 +0000 Subject: [PATCH 7/8] docs(connectors): let writers set ACL enforcement (PRO-3222) Signed-off-by: SohamRatnaparkhi <92905626+SohamRatnaparkhi@users.noreply.github.com> Co-authored-by: Soham Ratnaparkhi --- api-reference/v2/endpoint/connectors-overview.mdx | 6 +++--- api-reference/v2/endpoint/create-connector.mdx | 4 ++-- api-reference/v2/endpoint/update-connector.mdx | 4 ++-- api-reference/v2/openapi.json | 12 ++++++------ essentials/v2/access-control.mdx | 2 +- essentials/v2/connectors.mdx | 8 ++++---- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/api-reference/v2/endpoint/connectors-overview.mdx b/api-reference/v2/endpoint/connectors-overview.mdx index fefcdae2..e759091c 100644 --- a/api-reference/v2/endpoint/connectors-overview.mdx +++ b/api-reference/v2/endpoint/connectors-overview.mdx @@ -25,7 +25,7 @@ Check on it: Change it: -- [Update Connector](/api-reference/v2/endpoint/update-connector): `PATCH /connectors/{id}` changes the sync interval, connector-level instructions, credentials or the owner-only ACL enforcement setting. +- [Update Connector](/api-reference/v2/endpoint/update-connector): `PATCH /connectors/{id}` changes the sync interval, connector-level instructions, credentials or the ACL enforcement setting. - [Update Connector Resource](/api-reference/v2/endpoint/update-connector-resource): `PATCH /connectors/{id}/resources/{resource_id}` changes one resource's instructions or access rule. - [Add Connector Resource](/api-reference/v2/endpoint/add-connector-resource): `POST /connectors/{id}/resources` adds one new resource. - [Delete Connector Resource](/api-reference/v2/endpoint/delete-connector-resource): `DELETE /connectors/{id}/resources/{resource_id}` stops syncing a resource. @@ -46,7 +46,7 @@ After that, syncs run every `sync_interval_seconds` (one hour by default). Call To change a resource that is already configured, use `PATCH /connectors/{id}/resources/{resource_id}` or `POST /connectors/{id}/configure`. `POST /connectors/{id}/resources` adds new resources only: on an existing `resource_id` it returns `409` and changes nothing. - Instructions or access rule on one resource: `PATCH /connectors/{id}/resources/{resource_id}`. Only the fields you send change. -- Instructions, sync interval, credentials or ACL enforcement for the whole connector: `PATCH /connectors/{id}`. Only the fields you send change. Only a workspace owner in a signed-in dashboard session can set `enforce_acl`; API keys cannot change it. +- Instructions, sync interval, credentials or ACL enforcement for the whole connector: `PATCH /connectors/{id}`. Only the fields you send change. Only workspace owners and writers in a signed-in dashboard session can set `enforce_acl`; readers can view the current setting but cannot change it, and API keys cannot set it. - Name, type, database, collection or metadata of resources: `POST /connectors/{id}/configure`. Resources you leave out of the list are not touched. For each resource you list, send `name` and `resource_type` every time, because omitted values are cleared. Its sync position, instructions and access rule are kept. - A brand new resource: `POST /connectors/{id}/configure` or `POST /connectors/{id}/resources`. @@ -61,7 +61,7 @@ Authorization: Bearer $HYDRA_DB_API_KEY API-Version: 2 ``` -To set `enforce_acl`, use a workspace owner's signed-in dashboard session instead; API-key-authenticated requests cannot set it. +To set `enforce_acl`, use a signed-in dashboard session for a workspace owner or writer instead; API-key-authenticated requests cannot set it. ## Key concepts diff --git a/api-reference/v2/endpoint/create-connector.mdx b/api-reference/v2/endpoint/create-connector.mdx index ba2263b5..c40f1e13 100644 --- a/api-reference/v2/endpoint/create-connector.mdx +++ b/api-reference/v2/endpoint/create-connector.mdx @@ -12,7 +12,7 @@ Optional settings you can also pass here, and change later with [Update Connecto - `custom_instructions`: guidance for how this connector's documents are interpreted and indexed. See [Custom Ingestion Instructions](/essentials/v2/connectors#custom-ingestion-instructions). - `sync_interval_seconds`: how often scheduled syncs run. Omit it for the provider default (one hour for most providers). -- `enforce_acl`: whether content reads always enforce ACL for the authenticated caller for this connector. It defaults to `false` when omitted. Only a workspace owner in a signed-in dashboard session can set it, and `true` requires the provider to report `acl_supported: true`. API-key-authenticated requests must omit this field. An owner can enable or change it later with [Update Connector](/api-reference/v2/endpoint/update-connector) or in the dashboard. See [ACL on synced content](/essentials/v2/connectors#enforce-acl) for how caller identity and request `acl` behave. +- `enforce_acl`: whether content reads always enforce ACL for the authenticated caller for this connector. It defaults to `false` when omitted. Only workspace owners and writers in a signed-in dashboard session can set it, and `true` requires the provider to report `acl_supported: true`. API-key-authenticated requests must omit this field. An owner or writer can enable or change it later with [Update Connector](/api-reference/v2/endpoint/update-connector) or in the dashboard. See [ACL on synced content](/essentials/v2/connectors#enforce-acl) for how caller identity and request `acl` behave. @@ -85,7 +85,7 @@ curl -X POST 'https://api.hydradb.com/connectors' \ - `400`: `provider` or `database` is missing, the provider is unknown, or a setting such as `sync_interval_seconds` is out of range. - `402`: your plan's connector limit is reached. -- `403`: the provider is not available to your organization, or the request tries to set `enforce_acl` without a workspace owner's signed-in dashboard session. +- `403`: the provider is not available to your organization, or the request tries to set `enforce_acl` without a signed-in dashboard session for a workspace owner or writer. The ACL authorization error message is `only workspace owners and writers can change ACL enforcement`. - `422`: `credentials` does not match the provider's `credential_schema`.
diff --git a/api-reference/v2/endpoint/update-connector.mdx b/api-reference/v2/endpoint/update-connector.mdx index 2547be17..e48f179a 100644 --- a/api-reference/v2/endpoint/update-connector.mdx +++ b/api-reference/v2/endpoint/update-connector.mdx @@ -12,7 +12,7 @@ Update a connector's instructions, sync interval, credentials, or ACL enforcemen - `custom_instructions` applies to resources without their own instructions. Maximum 4,000 characters. Send `""` to clear it. Changes affect future syncs. See [Custom Ingestion Instructions](/essentials/v2/connectors#custom-ingestion-instructions). - `sync_interval_seconds` reschedules the next sync. Stay within the returned `min_sync_interval_seconds` and `max_sync_interval_seconds`, or send `0` for the provider default. - `credentials` reconnects the existing connector. Send the provider's complete credential set. Resources and saved sync positions are preserved. -- `enforce_acl` enables or disables caller-bound enforcement of this connector's captured ACL. Existing connectors remain `false` until an owner enables it. Send `true` to enforce captured ACL on every content read, or `false` to return to opt-in request `acl` filtering. Omit it to keep the current value. The change takes effect on the next content request for already-synced documents and does not require re-ingestion. Only a workspace owner in a signed-in dashboard session can set it; `true` requires the provider to report `acl_supported: true`. API-key-authenticated requests cannot set it. See [ACL on synced content](/essentials/v2/connectors#enforce-acl) and [Access Control](/essentials/v2/access-control). +- `enforce_acl` enables or disables caller-bound enforcement of this connector's captured ACL. Existing connectors remain `false` until an owner or writer enables it. Send `true` to enforce captured ACL on every content read, or `false` to return to opt-in request `acl` filtering. Omit it to keep the current value. The change takes effect on the next content request for already-synced documents and does not require re-ingestion. Only workspace owners and writers in a signed-in dashboard session can set it; `true` requires the provider to report `acl_supported: true`. API-key-authenticated requests cannot set it. See [ACL on synced content](/essentials/v2/connectors#enforce-acl) and [Access Control](/essentials/v2/access-control). To enable enforcement later, send this field in a PATCH request, or use **Enforce ACL** in the dashboard's connector settings: @@ -81,7 +81,7 @@ curl -X PATCH 'https://api.hydradb.com/connectors/{id}' \ ## Errors - `400`: the request includes an unsupported field, the provider does not report `acl_supported` for `enforce_acl: true`, `custom_instructions` is over 4,000 characters, or `sync_interval_seconds` is outside the provider's range. Nothing is changed. -- `403`: the request tries to set `enforce_acl` without a workspace owner's signed-in dashboard session. +- `403`: the request tries to set `enforce_acl` without a signed-in dashboard session for a workspace owner or writer. The ACL authorization error message is `only workspace owners and writers can change ACL enforcement`. - `404`: no connector with this id in your organization. - `422`: `credentials` does not match the provider's `credential_schema`. diff --git a/api-reference/v2/openapi.json b/api-reference/v2/openapi.json index baee3ecd..2337e548 100644 --- a/api-reference/v2/openapi.json +++ b/api-reference/v2/openapi.json @@ -3309,7 +3309,7 @@ "type": "string" }, "enforce_acl": { - "description": "Optional owner-only setting; defaults to false. True requires provider `acl_supported` and enables caller-bound reads; false keeps request `acl` as an opt-in filter.", + "description": "Optional setting for workspace owners and writers in a signed-in dashboard session; defaults to false. API keys cannot set it. True requires provider `acl_supported` and enables caller-bound reads; false keeps request `acl` as an opt-in filter.", "example": true, "type": "boolean" }, @@ -3920,7 +3920,7 @@ "type": "string" }, "enforce_acl": { - "description": "Set whether the connector enforces ACL. Omit to keep the current value; only a workspace owner may set it. True requires provider catalog `acl_supported`.", + "description": "Set whether the connector enforces ACL. Omit to keep the current value; only workspace owners and writers in a signed-in dashboard session may set it. Readers can view the current setting but cannot change it; API keys cannot set it. True requires provider catalog `acl_supported`.", "example": true, "type": "boolean" }, @@ -8078,7 +8078,7 @@ "x-fern-sdk-method-name": "list" }, "post": { - "description": "Create a connector for a provider and store its credentials. `enforce_acl` defaults to false when omitted, so writers may create connectors without choosing the setting. Only a workspace owner in a human dashboard session may explicitly set it, and true is accepted only when the provider catalog reports acl_supported. When true, content reads always use the authenticated caller; when false, request `acl` remains an opt-in filter.", + "description": "Create a connector for a provider and store its credentials. `enforce_acl` defaults to false when omitted, so writers may create connectors without choosing the setting. Only workspace owners and writers in a human dashboard session may explicitly set it; API keys cannot set it, and true is accepted only when the provider catalog reports acl_supported. When true, content reads always use the authenticated caller; when false, request `acl` remains an opt-in filter.", "requestBody": { "content": { "application/json": { @@ -8119,7 +8119,7 @@ } } }, - "description": "Setting enforce_acl requires a workspace owner in a signed-in dashboard session." + "description": "Setting enforce_acl requires a workspace owner or writer in a signed-in dashboard session; API keys cannot set it. The ACL authorization error message is: only workspace owners and writers can change ACL enforcement" }, "500": { "content": { @@ -8330,7 +8330,7 @@ "x-fern-sdk-method-name": "get" }, "patch": { - "description": "Update the supplied connector settings. Use `credentials` to reconnect, `sync_interval_seconds` to change cadence, `custom_instructions` to change ingestion instructions, or `enforce_acl` to set the owner-only enforcement mode. True requires provider catalog `acl_supported`; when enabled, content reads use the authenticated caller, while false keeps request `acl` as an opt-in filter.", + "description": "Update the supplied connector settings. Use `credentials` to reconnect, `sync_interval_seconds` to change cadence, `custom_instructions` to change ingestion instructions, or `enforce_acl` to set the enforcement mode (workspace owners and writers in a signed-in dashboard session only; API keys cannot set it). True requires provider catalog `acl_supported`; when enabled, content reads use the authenticated caller, while false keeps request `acl` as an opt-in filter.", "parameters": [ { "description": "Connector ID", @@ -8383,7 +8383,7 @@ } } }, - "description": "Setting enforce_acl requires a workspace owner in a signed-in dashboard session." + "description": "Setting enforce_acl requires a workspace owner or writer in a signed-in dashboard session; API keys cannot set it. The ACL authorization error message is: only workspace owners and writers can change ACL enforcement" }, "404": { "content": { diff --git a/essentials/v2/access-control.mdx b/essentials/v2/access-control.mdx index cdf57e64..06159178 100644 --- a/essentials/v2/access-control.mdx +++ b/essentials/v2/access-control.mdx @@ -229,7 +229,7 @@ For supported providers, HydraDB captures the provider's ACL on every sync, so y Capture is also built for GitLab, Linear, Dropbox, Zendesk, PagerDuty, Typeform, Attio, LaunchDarkly, ServiceNow, Microsoft Teams, and Outlook, and is switched on per provider. The [provider catalog](/api-reference/v2/endpoint/list-connector-providers) reports capture support in `acl_supported` and summarizes it in `acl_description`. Check [Get Connector Status](/api-reference/v2/endpoint/get-connector-status) for an `acl_warning` after the first sync. For any other provider, [set your own rule on the resource](#set-your-own-rule-on-a-resource). -By default, captured ACLs are not enforced automatically on reads. A workspace owner can enable per-connector enforcement with `enforce_acl`, which is available only when the provider supports `acl_supported`. With enforcement enabled, the authenticated caller replaces a request's `acl` for content from that connector; an `acl` supplied on the request still scopes content from non-enforced connectors. See [ACL on synced content](/essentials/v2/connectors#enforce-acl) for the identity rules and the machine-readable warning returned when an `acl` is overridden. +By default, captured ACLs are not enforced automatically on reads. A workspace owner or writer can enable per-connector enforcement with `enforce_acl`, which is available only when the provider supports `acl_supported`. With enforcement enabled, the authenticated caller replaces a request's `acl` for content from that connector; an `acl` supplied on the request still scopes content from non-enforced connectors. See [ACL on synced content](/essentials/v2/connectors#enforce-acl) for the identity rules and the machine-readable warning returned when an `acl` is overridden. ### Set your own rule on a resource diff --git a/essentials/v2/connectors.mdx b/essentials/v2/connectors.mdx index 407e6b3d..6cb0708a 100644 --- a/essentials/v2/connectors.mdx +++ b/essentials/v2/connectors.mdx @@ -277,7 +277,7 @@ curl -X POST 'https://api.hydradb.com/connectors/{id}/configure' \ | `credentials` | create | The provider's credentials, in the shape of its `credential_schema`. Credentials that do not match the schema are rejected with `422`. | | `custom_instructions` | create, configure | Guidance for how synced documents are interpreted, for the whole connector or for one resource. See [section 4](#4-custom-ingestion-instructions). | | `sync_interval_seconds` | create | How often scheduled syncs run. Omit it for the provider default, one hour for most providers. | -| `enforce_acl` | create, update | Whether reads from this connector always enforce ACL for the authenticated caller. Optional and `false` by default. Only a workspace owner can set it, and enabling it requires a provider with `acl_supported`. See [ACL enforcement](#enforce-acl). | +| `enforce_acl` | create, update | Whether reads from this connector always enforce ACL for the authenticated caller. Optional and `false` by default. Only workspace owners and writers can set it, and enabling it requires a provider with `acl_supported`. See [ACL enforcement](#enforce-acl). | | `lookback_days` | configure | How much history the first sync fetches (default `30`). After that, each sync fetches only what is new. Above 30, some providers fetch the older history in the background and the response reports `backfill: true`. | | `resource_id`, `resource_type`, `name` | configure | The `id`, `resource_type`, and `name` of an entry from discover. Send all three every time you list a resource. | | `metadata` | configure | Fields merged into the database metadata of every object from this resource. Declare the ones you filter on in your database's [metadata schema](/essentials/v2/metadata). | @@ -513,13 +513,13 @@ To see which provider-native fields a connector writes, call [`GET /connectors/p For supported providers, HydraDB captures ACL from the provider on every sync. Slack, Google Drive, GitHub, Confluence, and Jira are among the supported providers; [Access Control](/essentials/v2/access-control) lists what is captured for each. Capture and enforcement are separate: the connector's `enforce_acl` setting controls ACL enforcement on reads. -By default, `enforce_acl` is `false`. Omitting it on create leaves the new connector unenforced, and existing connectors remain unenforced until an owner enables the setting. In this mode, access control remains opt-in on each request: send the caller's identity in `acl` to filter content, and a request without `acl` is not filtered by caller identity. This remains true for content from connectors whose enforcement is disabled, even when the same request also reads enforced connector content. MCP OAuth does not enforce caller identity for a non-enforced connector; send `acl` when that request needs caller filtering. +By default, `enforce_acl` is `false`. Omitting it on create leaves the new connector unenforced, and existing connectors remain unenforced until an owner or writer enables the setting. In this mode, access control remains opt-in on each request: send the caller's identity in `acl` to filter content, and a request without `acl` is not filtered by caller identity. This remains true for content from connectors whose enforcement is disabled, even when the same request also reads enforced connector content. MCP OAuth does not enforce caller identity for a non-enforced connector; send `acl` when that request needs caller filtering. ### Enforce ACL -Set `enforce_acl` to `true` to make reads from this connector use the authenticated caller's identity against the ACL HydraDB captured. The provider must report `acl_supported: true` in [List Connector Providers](/api-reference/v2/endpoint/list-connector-providers). The setting is optional on [`POST /connectors`](/api-reference/v2/endpoint/create-connector), defaults to `false`, and can be enabled or changed later with [`PATCH /connectors/{id}`](/api-reference/v2/endpoint/update-connector). In the dashboard, an owner can use the **Enforce ACL** control in the connector settings. A change takes effect on the next content request for already-synced documents and does not require re-ingestion. +Set `enforce_acl` to `true` to make reads from this connector use the authenticated caller's identity against the ACL HydraDB captured. The provider must report `acl_supported: true` in [List Connector Providers](/api-reference/v2/endpoint/list-connector-providers). The setting is optional on [`POST /connectors`](/api-reference/v2/endpoint/create-connector), defaults to `false`, and can be enabled or changed later with [`PATCH /connectors/{id}`](/api-reference/v2/endpoint/update-connector). In the dashboard, an owner or writer can use the **Enforce ACL** control in the connector settings. A change takes effect on the next content request for already-synced documents and does not require re-ingestion. -Only a workspace owner can set or change this setting. The API requires an owner in a signed-in dashboard session; API-key-authenticated requests can create a connector with the default `false` value, but cannot choose or change the setting. +Only workspace owners and writers can set or change this setting. Readers can view the current setting but cannot change it. The API requires an owner or writer in a signed-in dashboard session; API-key-authenticated requests can create a connector with the default `false` value, but cannot choose or change the setting. When enforcement is enabled, HydraDB selects the identity from authentication rather than trusting a caller-supplied `acl`: From 61a07886dc324e917388cf5bc7d30dd9df20d220 Mon Sep 17 00:00:00 2001 From: Soham Ratnaparkhi Date: Thu, 29 Oct 2026 00:50:54 +0530 Subject: [PATCH 8/8] docs(acl): Drive group membership, key revocation, and leave the spec to autogen - Access Control: a Google Drive-only section on files shared with a group: what google_group_membership_resolves reports, why a false result keeps group-shared files restricted, and the fix (reconnect as a Workspace admin with Directory access). States that no other connector reports it. - Connectors: removing a member, or a member leaving, revokes every key they created in the workspace, and re-inviting restores none. A provider whose acl_supported HydraDB withdraws stops enforcing and keeps enforce_acl. - Update Connector: the 503 when the provider catalog cannot be read while enabling enforce_acl. - api-reference/v2/openapi.json goes back to main. The generated spec (#343) now carries acl_supported, acl_description and enforce_acl from the API's own annotations, so this PR no longer hand-edits it and the two do not conflict. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Soham Ratnaparkhi --- .../v2/endpoint/update-connector.mdx | 1 + api-reference/v2/openapi.json | 107 +++--------------- essentials/v2/access-control.mdx | 13 +++ essentials/v2/connectors.mdx | 4 +- 4 files changed, 33 insertions(+), 92 deletions(-) diff --git a/api-reference/v2/endpoint/update-connector.mdx b/api-reference/v2/endpoint/update-connector.mdx index e48f179a..23e0e981 100644 --- a/api-reference/v2/endpoint/update-connector.mdx +++ b/api-reference/v2/endpoint/update-connector.mdx @@ -84,6 +84,7 @@ curl -X PATCH 'https://api.hydradb.com/connectors/{id}' \ - `403`: the request tries to set `enforce_acl` without a signed-in dashboard session for a workspace owner or writer. The ACL authorization error message is `only workspace owners and writers can change ACL enforcement`. - `404`: no connector with this id in your organization. - `422`: `credentials` does not match the provider's `credential_schema`. +- `503`: HydraDB could not read its provider catalog to check `acl_supported` for `enforce_acl: true`. Nothing is changed. Retry the request.
diff --git a/api-reference/v2/openapi.json b/api-reference/v2/openapi.json index 2337e548..f9156676 100644 --- a/api-reference/v2/openapi.json +++ b/api-reference/v2/openapi.json @@ -2905,21 +2905,6 @@ "title": "HandlerErrorResponse", "type": "object" }, - "handler.ResponseWarning": { - "properties": { - "code": { - "description": "Code identifies the warning type, such as acl_ignored_by_connector_enforcement.", - "type": "string" - }, - "message": { - "description": "Human-readable explanation of the warning.", - "example": "This connector enforces ACL, so the request's acl was ignored.", - "type": "string" - } - }, - "title": "HandlerResponseWarning", - "type": "object" - }, "handler.apiError": { "properties": { "code": { @@ -2980,12 +2965,12 @@ "null" ] }, - "acl_description": { - "description": "One-line summary of the provider ACL captured as document access rules. Present when `acl_supported` is true.", + "rbac_description": { + "description": "One-line summary of which provider permissions are captured as document access rules. Not returned by this endpoint.", "type": "string" }, - "acl_supported": { - "description": "True when the provider captures ACL as document access rules. Connector ACL enforcement can be enabled only when this is true.", + "rbac_support": { + "description": "Reserved. Always `false` on this endpoint.", "example": true, "type": "boolean" }, @@ -3161,11 +3146,6 @@ "description": "RFC3339 timestamp of the first sync that sent at least one object for ingestion. Empty until then.", "type": "string" }, - "enforce_acl": { - "description": "Whether ACL enforcement is enabled. False when unsupported. When true, reads use the authenticated caller; otherwise request `acl` remains an opt-in filter.", - "example": true, - "type": "boolean" - }, "last_attempted_sync_at": { "description": "RFC3339 timestamp of the most recent sync attempt (successful or not).", "example": "2026-07-02T17:00:00Z", @@ -3308,11 +3288,6 @@ "example": "acme_corp", "type": "string" }, - "enforce_acl": { - "description": "Optional setting for workspace owners and writers in a signed-in dashboard session; defaults to false. API keys cannot set it. True requires provider `acl_supported` and enables caller-bound reads; false keeps request `acl` as an opt-in filter.", - "example": true, - "type": "boolean" - }, "name": { "description": "Human-readable label for this connector.", "example": "general", @@ -3398,11 +3373,6 @@ "description": "RFC3339 timestamp when the first scheduled sync runs.", "type": "string" }, - "enforce_acl": { - "description": "Whether ACL enforcement is enabled. False when unsupported. When true, reads use the authenticated caller; otherwise request `acl` remains an opt-in filter.", - "example": true, - "type": "boolean" - }, "last_attempted_sync_at": { "description": "RFC3339 timestamp of the most recent sync attempt (successful or not).", "example": "2026-07-02T17:00:00Z", @@ -3919,11 +3889,6 @@ "description": "Ingestion and indexing instructions for every resource on this connector that has no instructions of its own. Omit to leave unchanged; `\"\"` clears. Up to 4000 characters, applied from the next sync.", "type": "string" }, - "enforce_acl": { - "description": "Set whether the connector enforces ACL. Omit to keep the current value; only workspace owners and writers in a signed-in dashboard session may set it. Readers can view the current setting but cannot change it; API keys cannot set it. True requires provider catalog `acl_supported`.", - "example": true, - "type": "boolean" - }, "sync_interval_seconds": { "description": "How frequently the scheduler triggers incremental syncs, in seconds. Bounded per provider; send 0 or omit to use the provider default. Change it later with PATCH /connectors/{id}.", "example": 3600, @@ -3950,11 +3915,6 @@ "example": true, "type": "boolean" }, - "enforce_acl": { - "description": "Whether ACL enforcement is enabled. False when unsupported. When true, reads use the authenticated caller; otherwise request `acl` remains an opt-in filter.", - "example": true, - "type": "boolean" - }, "max_sync_interval_seconds": { "description": "Largest sync_interval_seconds this connector's provider allows.", "example": 604800, @@ -4386,10 +4346,9 @@ "is_beta": true, "moveit_support": true, "provider": "slack", - "acl_supported": true, + "rbac_support": true, "supported": true, - "webhook_support": true, - "acl_description": "Captures channel-level access: public channels are visible to the workspace, private channels only to their members." + "webhook_support": true } ], "items": { @@ -4869,20 +4828,6 @@ "example": "tenant_1234", "type": "string", "x-deprecated": "true" - }, - "warnings": { - "description": "Non-fatal response notices. When request `acl` is overridden for enforced connector content, exactly one warning has code `acl_ignored_by_connector_enforcement`.", - "example": [ - { - "code": "acl_ignored_by_connector_enforcement", - "message": "This connector enforces ACL, so the request's acl was ignored." - } - ], - "items": { - "$ref": "#/components/schemas/handler.ResponseWarning" - }, - "type": "array", - "uniqueItems": false } }, "title": "HandlerResponseMeta", @@ -5345,7 +5290,7 @@ "list.V2ListContentRequest": { "properties": { "acl": { - "description": "Principals to answer as. For directly ingested knowledge and non-enforced connectors, only context visible to these principals is listed. Enforced connector content uses the authenticated caller instead. If sent and overridden, one `meta.warnings` entry has code `acl_ignored_by_connector_enforcement`.", + "description": "Principals to answer as: only context they may see is listed. Omit it for no access scoping.", "items": { "type": "string" }, @@ -6241,7 +6186,7 @@ "search.QueryRequest": { "properties": { "acl": { - "description": "Principals to query as: emails or `user_email:`, `group:` or `domain:` principals. For directly ingested knowledge and non-enforced connectors, returns their context plus public and unrestricted context. Enforced connectors use the authenticated caller instead. If sent and overridden, one `meta.warnings` entry has code `acl_ignored_by_connector_enforcement`. Omit, `[]` or `[\"*\"]` to disable caller-supplied filtering for non-enforced connectors.", + "description": "Principals to query as: emails or `user_email:`, `group:` or `domain:` principals. Returns their context plus public and unrestricted context. Omit, `[]` or `[\"*\"]` for no scoping.", "items": { "type": "string" }, @@ -8078,7 +8023,7 @@ "x-fern-sdk-method-name": "list" }, "post": { - "description": "Create a connector for a provider and store its credentials. `enforce_acl` defaults to false when omitted, so writers may create connectors without choosing the setting. Only workspace owners and writers in a human dashboard session may explicitly set it; API keys cannot set it, and true is accepted only when the provider catalog reports acl_supported. When true, content reads always use the authenticated caller; when false, request `acl` remains an opt-in filter.", + "description": "Create a connector for a provider and store its credentials.", "requestBody": { "content": { "application/json": { @@ -8111,16 +8056,6 @@ }, "description": "Bad Request" }, - "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/handler.ErrorResponse" - } - } - }, - "description": "Setting enforce_acl requires a workspace owner or writer in a signed-in dashboard session; API keys cannot set it. The ACL authorization error message is: only workspace owners and writers can change ACL enforcement" - }, "500": { "content": { "application/json": { @@ -8157,7 +8092,7 @@ }, "/connectors/providers": { "get": { - "description": "Lists the providers you can connect, including whether ACL capture is supported (`acl_supported`) and its summary (`acl_description`). With `id`, describes one provider: its searchable object types and fields (with `filter_key`), `credential_schema`, and `setup_guide` when needed.", + "description": "Lists the providers you can connect. With `id`, describes one: its searchable object types and fields (with `filter_key`), `credential_schema`, and `setup_guide` when needed.", "parameters": [ { "description": "Provider name (e.g. slack, gmail). Omit to list all.", @@ -8330,7 +8265,7 @@ "x-fern-sdk-method-name": "get" }, "patch": { - "description": "Update the supplied connector settings. Use `credentials` to reconnect, `sync_interval_seconds` to change cadence, `custom_instructions` to change ingestion instructions, or `enforce_acl` to set the enforcement mode (workspace owners and writers in a signed-in dashboard session only; API keys cannot set it). True requires provider catalog `acl_supported`; when enabled, content reads use the authenticated caller, while false keeps request `acl` as an opt-in filter.", + "description": "Update the supplied connector settings. Use `credentials` to reconnect, `sync_interval_seconds` to change cadence, or `custom_instructions` to change ingestion instructions.", "parameters": [ { "description": "Connector ID", @@ -8375,16 +8310,6 @@ }, "description": "Bad Request" }, - "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/handler.ErrorResponse" - } - } - }, - "description": "Setting enforce_acl requires a workspace owner or writer in a signed-in dashboard session; API keys cannot set it. The ACL authorization error message is: only workspace owners and writers can change ACL enforcement" - }, "404": { "content": { "application/json": { @@ -9545,7 +9470,7 @@ } }, { - "description": "Principals to inspect as. For directly ingested knowledge and non-enforced connector content, only contexts visible to these principals can be inspected; a context that is not visible returns `404`. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values. If sent and overridden, one `meta.warnings` entry has code `acl_ignored_by_connector_enforcement`.", + "description": "Principals to answer as. The context must be visible to them, or the response is `404`. Repeated (`acl=a\u0026acl=b`) or comma-separated. Omit it for no access scoping.", "in": "query", "name": "acl", "schema": { @@ -9737,7 +9662,7 @@ } }, { - "description": "Principals to answer as. For directly ingested knowledge and non-enforced connector content, only results visible to these principals are returned. Enforced connector content uses the authenticated caller instead. Repeat the parameter or send a comma-separated list. If sent and overridden, one `meta.warnings` entry has code `acl_ignored_by_connector_enforcement`.", + "description": "Principals to answer as; only results they may see are returned. Repeat the parameter or send a comma-separated list. Omit it for no scoping.", "in": "query", "name": "acl", "schema": { @@ -9983,7 +9908,7 @@ } }, { - "description": "Principals to answer as. For directly ingested knowledge and non-enforced connector content, only contexts visible to these principals are returned, checked at every hop. Enforced connector content uses the authenticated caller instead. Repeat or comma-separate values. If sent and overridden, one `meta.warnings` entry has code `acl_ignored_by_connector_enforcement`.", + "description": "Principals to answer as; only contexts they may see are returned, checked at every hop. Omit for no access scoping. Repeat or comma-separate.", "in": "query", "name": "acl", "schema": { @@ -10202,7 +10127,7 @@ } }, { - "description": "Principals allowed to read the returned contexts. For directly ingested knowledge and non-enforced connector content, only contexts visible to these principals are returned. Enforced connector content uses the authenticated caller instead for every returned context. If sent and overridden, one `meta.warnings` entry has code `acl_ignored_by_connector_enforcement`.", + "description": "Principals allowed to read the returned contexts. Omit for no additional scoping.", "in": "query", "name": "acl", "schema": { @@ -11426,4 +11351,4 @@ "x-fern-default": "2" } ] -} +} \ No newline at end of file diff --git a/essentials/v2/access-control.mdx b/essentials/v2/access-control.mdx index 06159178..5e71b767 100644 --- a/essentials/v2/access-control.mdx +++ b/essentials/v2/access-control.mdx @@ -231,6 +231,19 @@ Capture is also built for GitLab, Linear, Dropbox, Zendesk, PagerDuty, Typeform, By default, captured ACLs are not enforced automatically on reads. A workspace owner or writer can enable per-connector enforcement with `enforce_acl`, which is available only when the provider supports `acl_supported`. With enforcement enabled, the authenticated caller replaces a request's `acl` for content from that connector; an `acl` supplied on the request still scopes content from non-enforced connectors. See [ACL on synced content](/essentials/v2/connectors#enforce-acl) for the identity rules and the machine-readable warning returned when an `acl` is overridden. +### Google Drive files shared with a group + +This section applies only to Google Drive. No other connector expands groups this way or reports this check. + +A Drive file shared with a Google Group carries the grant `group:google:`. To let group members read it, HydraDB reads the group's members through the Google Workspace Directory API. That needs a Drive connection made by a Workspace admin with Directory access. + +When you connect Google Drive, HydraDB checks this access once. The connection check reports the result as `google_group_membership_resolves`, and the dashboard shows it as a notice: + +- `true`: group membership can be read. Members of a group can read the files shared with that group. +- `false`: group membership cannot be read. A file shared only through a group keeps its `group:google:` grant, which no caller matches, so the file stays restricted. With ACL enforcement on, group members cannot see it. A request `acl` sees it only if it names the group. The same applies to a group too large to expand. + +To fix `false`, reconnect Google Drive as a Workspace admin with Directory access. + ### Set your own rule on a resource Every object synced from a resource inherits the resource's rule. Set it when you [configure the connector](/api-reference/v2/endpoint/configure-connector), or change it later on its own with [Update Connector Resource](/api-reference/v2/endpoint/update-connector-resource). The change applies to every already-synced document from that resource on the next query, with no re-sync and no re-index. diff --git a/essentials/v2/connectors.mdx b/essentials/v2/connectors.mdx index 6cb0708a..fd011006 100644 --- a/essentials/v2/connectors.mdx +++ b/essentials/v2/connectors.mdx @@ -519,6 +519,8 @@ By default, `enforce_acl` is `false`. Omitting it on create leaves the new conne Set `enforce_acl` to `true` to make reads from this connector use the authenticated caller's identity against the ACL HydraDB captured. The provider must report `acl_supported: true` in [List Connector Providers](/api-reference/v2/endpoint/list-connector-providers). The setting is optional on [`POST /connectors`](/api-reference/v2/endpoint/create-connector), defaults to `false`, and can be enabled or changed later with [`PATCH /connectors/{id}`](/api-reference/v2/endpoint/update-connector). In the dashboard, an owner or writer can use the **Enforce ACL** control in the connector settings. A change takes effect on the next content request for already-synced documents and does not require re-ingestion. +HydraDB decides which providers report `acl_supported`. If it stops reporting it for a provider, that provider's connectors stop enforcing within about a minute and keep their stored `enforce_acl` value. Enforcement resumes when support returns. + Only workspace owners and writers can set or change this setting. Readers can view the current setting but cannot change it. The API requires an owner or writer in a signed-in dashboard session; API-key-authenticated requests can create a connector with the default `false` value, but cannot choose or change the setting. When enforcement is enabled, HydraDB selects the identity from authentication rather than trusting a caller-supplied `acl`: @@ -542,7 +544,7 @@ If a content-read request includes `acl`, HydraDB ignores it for content from co } ``` -An API key stays tied to its creator. When a member is removed from the workspace, that member's API keys stop working; another member must use a key created under their own account. +An API key stays tied to its creator. When a member is removed from the workspace, or leaves it, every API key they created in that workspace is revoked. Re-inviting them does not restore those keys; they create new ones. Another member must use a key created under their own account. Your own rule per resource goes in `acl` at configure time, or afterwards on its own: