Skip to main content
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, or later on an existing source (section 4). Connectors can capture app permissions or apply your resource rules. Memories are scoped per user with collection instead. In this guide:
  1. Set an ACL on an item and query as someone: restrict a Slack message, then query as one person.
  2. Principals: the five identity forms, and what a query’s acl list can contain.
  3. Let connectors capture permissions: which providers copy their own permissions, and how your own rule per resource fits in.
  4. Change or revoke access: editing an ACL without re-ingesting, and when each change takes effect.
  5. Common mistakes and related pages.

1. Set an ACL on an item and query as someone

This example ingests one Slack message that only Grace and the members of channel C0123 may retrieve, then runs a query on Grace’s behalf. Every app source takes the same acl list; only the item changes.
Set up your SDK client before running the Python or TypeScript example.
Wait for GET /context/status to report completed for slack-C0123-1712345678 in the engineering collection, then query as Grace.

What each property means

What a query returns

A document comes back when its acl is absent (unrestricted), when it is __public__, or when it names one of the caller’s principals. HydraDB checks this on every search path (semantic, keyword, and graph), so a document the caller may not see never reaches the results. Take six documents in one collection: The same question returns different documents depending on who asks: Access control works alongside metadata filters: filters say what you are looking for, ACLs say what you are allowed to find, and a filter can never widen what a caller may see. 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.

2. Principals

A principal is an identity written as a string: one person, a group, or everyone in a domain. These are the five forms: Principals are lowercased, trimmed, and deduplicated on the way in. __public__ overrides everything else in the same list: a public document is public. __private__ only means something on its own; alongside real principals it is dropped. A document holds at most 1,000 principals of at most 256 characters each. For larger audiences use a group: or domain: principal. Absent is not empty: a document with no acl is unrestricted. Every document ingested before you adopted access control behaves this way, so adopting it never hides existing documents. A document you restrict to nobody is stored as __private__; on an item, "acl": [] means nobody, not everybody.

What the query’s acl list can contain

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

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: 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 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

Every object synced from a resource inherits the resource’s rule. Set it when you configure the connector, or change it later on its own with 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.
At configure time, each entry in resources can carry its own acl:
Afterwards, change the rule on its own without touching anything else:

When the provider’s permissions and your rule disagree

  • A per-document permission 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 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.

4. Change or revoke access

To change who may retrieve a document you already ingested, send acl to PATCH /context/{id}/metadata. Unlike the metadata fields on that endpoint, acl replaces the stored list rather than merging into it: to add a third person, send all three. An acl-only body is a valid edit.
The three wire states are distinct: The response carries acl_updated: true. If vector_acl_synced is missing from it, the new list is still enforced, but a newly added person may miss this document in results until it is re-indexed.

When a change takes effect

Deleting a rule does not widen access on its own: visibility only ever widens from a value you positively set. To open a restricted resource back up, set its ACL to ["__public__"] rather than clearing it.

Common mistakes

The queries are not declaring an identity. Add "acl": ["<caller email>"] to each query.
Check the principal forms on both sides. group:slack:C0123 on the document only matches a query that declares that same group; unlike domain:, group membership is not derived from the caller’s email. Also confirm the email matches exactly: principals are compared after lowercasing and trimming, but not otherwise fuzzy-matched.