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:
- Set an ACL on an item and query as someone: restrict a Slack message, then query as one person.
- Principals: the five identity forms, and what a query’s
acllist can contain. - Let connectors capture permissions: which providers copy their own permissions, and how your own rule per resource fits in.
- Change or revoke access: editing an ACL without re-ingesting, and when each change takes effect.
- 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 channelC0123 may retrieve, then runs a query on Grace’s behalf. Every app source takes the same acl list; only the item changes.
Ingest a restricted message and query as Grace: Python, TypeScript, or cURL
Ingest a restricted message and query as Grace: Python, TypeScript, or cURL
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 itsacl 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.
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.Set a resource rule at configure time or afterwards: JSON, Python, TypeScript, or cURL
Set a resource rule at configure time or afterwards: JSON, Python, TypeScript, or cURL
At configure time, each entry in Afterwards, change the rule on its own without touching anything else:
resources can carry its own acl: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.
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, sendacl 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.
Replace a document's ACL without re-ingesting: Python, TypeScript, or cURL
Replace a document's ACL without re-ingesting: Python, TypeScript, or cURL
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
ACLs are set but every query still returns everything
ACLs are set but every query still returns everything
The queries are not declaring an identity. Add
"acl": ["<caller email>"] to each query.A caller who should see a document sees nothing
A caller who should see a document sees nothing
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.Related
- Connectors: syncing app data, and per-resource ACL rules
- App Sources: the ingest shape that carries
acl - Query: the
aclfield alongside every other retrieval parameter - Metadata: filtering by attributes, a different question from permission
- Multi-tenancy: databases and collections, the isolation boundary ACLs work inside
- Update Source Metadata (API Reference): the
aclreplacement contract - Update Connector Resource (API Reference): the per-resource rule
