LangChain / ChromaDB adapter :: Cerbos Authorization Management Platform // Documentation
LangChain / ChromaDB adapter
| This documentation is for an as-yet unreleased version of Cerbos PDP. Choose 0.53.0 from the version picker at the top right or navigate to https://docs.cerbos.dev for the latest version. |
The @cerbos/langchain-chromadb package converts a Cerbos PlanResources response into a ChromaDB Where filter object compatible with the LangChain.js Chroma vector store. This enables authorization-aware similarity searches where Cerbos policy conditions are pushed down as metadata filters.
Requirements
Cerbos >= v0.16
@cerbos/httpor@cerbos/grpcclientChromaDB 3.x
Node.js >= 20.0.0
Installation
npm install @cerbos/langchain-chromadb
Supported operators
| Category | Operators |
|---|---|
| Logical | and, or — $and, $or |
| Negation | not — operator inversion via De Morgan’s law (see below) |
| Comparison | eq, ne, lt, le, gt, ge — $eq, $ne, $lt, $lte, $gt, $gte |
| Membership | in — $in |
Negation handling
ChromaDB has no $not or $nor filter. The adapter handles not expressions by inverting the inner operator:
not(eq)becomes$ne;not(ne)becomes$eqnot(lt)becomes$gte;not(gt)becomes$lte;not(le)becomes$gt;not(ge)becomes$ltnot(in)becomes$ninnot(and(A, B))becomes$or[not(A), not(B)](De Morgan’s law)not(or(A, B))becomes$and[not(A), not(B)](De Morgan’s law)not(not(X))becomesX(double negation elimination)
Unsupported operators
ChromaDB stores flat scalar metadata. The following operators cannot be mapped and cause queryPlanToChromaDB to throw an error:
String:
contains,startsWith,endsWithExistence:
isSetCollection:
hasIntersection,exists,exists_one,all,filter,map,lambda,size
Usage
import { queryPlanToChromaDB, PlanKind } from "@cerbos/langchain-chromadb";
import { Chroma } from "@langchain/community/vectorstores/chroma";
import { OpenAIEmbeddings } from "@langchain/openai";
const queryPlan = await cerbos.planResources({
principal: { id: "user1", roles: ["USER"] },
resource: { kind: "document" },
action: "view",
});
const result = queryPlanToChromaDB({
queryPlan,
fieldNameMapper: {
"request.resource.attr.department": "department",
"request.resource.attr.public": "public",
},
});
if (result.kind === PlanKind.ALWAYS_DENIED) {
return [];
}
const chroma = await Chroma.fromExistingCollection(
new OpenAIEmbeddings(),
{ collectionName: "my_collection" },
);
const filters =
result.kind === PlanKind.CONDITIONAL ? result.filters : undefined;
const matches = await chroma.similaritySearch("query", 10, filters);
Field name mapper
The mapper translates Cerbos attribute references to ChromaDB metadata field names. It accepts an object or a function.
// Object mapper
const result = queryPlanToChromaDB({
queryPlan,
fieldNameMapper: {
"request.resource.attr.aBool": "aBool",
"request.resource.attr.aString": "title",
},
});
// Function mapper
const result = queryPlanToChromaDB({
queryPlan,
fieldNameMapper: (fieldName) =>
fieldName.replace("request.resource.attr.", ""),
});
If a field is not found in the object mapper, the original Cerbos path is used as-is.