Short answer: RBAC decides whether a credential may perform an operation at all, before scoping decides which memories that operation can reach.
Scopes answer which data; roles answer which actions are allowed. Least privilege gives each role only what its job needs, limiting blast radius if a credential is exposed. Distinct roles matter even when one team holds them. Engram uses Weaviate RBAC so callers cannot exceed their intended capabilities.
The previous chapter closed by pointing to a second, independent layer of protection sitting alongside structural scoping, one that controls not what a request can retrieve once it’s scoped correctly, but whether a given caller should even be allowed to issue that kind of request in the first place. This chapter looks at role-based access control, what it actually adds beyond scoping, and why memory systems specifically benefit from taking it seriously.
What Does Role-Based Access Control Actually Add on Top of the Scoping Already Covered in This Part?
Scoping determines which specific memories a correctly formed request can reach, a user’s own data, a specific conversation, a specific project. Role-based access control asks a different, earlier question entirely, whether the credential issuing this request should be allowed to perform this kind of operation at all, on any data, regardless of scope. A perfectly scoped request issued by a credential that never should have had this level of access in the first place is still a serious problem, one that scoping alone was never designed to catch.
Why Does a Memory System Specifically Benefit From This Distinction Between Roles and Scopes?
Memory systems tend to serve several genuinely different kinds of callers, a customer-facing application that only ever needs to read a user’s own memories, an internal analytics job that needs broader read access across many users for aggregate reporting, and an administrative tool that needs the ability to delete data outright for compliance reasons. These are fundamentally different levels of trust, and collapsing them all into one undifferentiated credential means a compromise or a mistake anywhere in the system carries the full weight of whatever that single credential could do, rather than being contained to whatever narrow role actually needed to be involved.
What Does Applying the Principle of Least Privilege Actually Look Like for the Different Roles a Memory System Typically Needs?
A customer-facing search feature generally needs only read access, scoped to whichever user is currently making the request, and nothing more, it has no legitimate reason to write new memories, delete existing ones, or read across users. An internal pipeline that extracts and commits new memories needs write access, but not necessarily delete access, since removing memories outright is usually a separate, more deliberate operation than the routine flow of storing new ones. An administrative tool handling data-deletion requests for compliance reasons needs exactly that, delete access, scoped narrowly to the specific operation it exists to perform, not broad standing access to read or modify everything else in the system.
Why Does Keeping These Roles Distinct Matter Even If, in Practice, the Same Team Manages All of Them?
Distinct roles matter independently of who happens to operate them, because the value of least privilege is in containing the blast radius of a single mistake or a single compromised credential, not in reflecting some organizational chart. If a customer-facing application’s credential is somehow exposed, a role restricted to read-only, single-user access limits what an attacker or a bug could actually do with it, while a shared, broadly privileged credential would turn that same exposure into a far more serious incident. The value shows up precisely in the failure case, not in ordinary day-to-day operation, which is exactly why it’s tempting to skip and exactly why skipping it is a mistake.
Does Assigning Roles This Way Actually Slow Down Development or Add Meaningful Friction to Building New Features?
It adds a small amount of upfront thought, deciding what a new component actually needs before granting it broad access by default, but it doesn’t meaningfully slow down the work itself once that decision is made. Creating a narrowly scoped role for a new feature is a one-time configuration step, not an ongoing tax on every request that feature ever makes, and the alternative, granting broad access because it’s the path of least resistance in the moment, simply defers the real cost to whenever that broad access eventually gets misused or exposed.
How Does Weaviate Engram Rely on Weaviate’s Own Role-Based Access Control to Restrict What Different Callers Can Actually Do?
Weaviate Engram builds on Weaviate’s role-based access control, letting an operator define distinct roles for different components of a system, each restricted to exactly the actions that component actually needs. Consider a telehealth platform where a patient-facing symptom-checker app should only ever read a patient’s own memory, while a separate compliance tool needs the ability to permanently delete a patient’s data upon request, and neither should be able to do the other’s job:
from weaviate.classes.rbac import Permissions
patient_app_permissions = [
Permissions.data(
collection="EngramMemories",
create=False,
read=True,
update=False,
delete=False,
),
]
compliance_tool_permissions = [
Permissions.data(
collection="EngramMemories",
create=False,
read=True,
update=False,
delete=True,
),
]
client.roles.create(role_name="patient_app_reader", permissions=patient_app_permissions)
client.roles.create(role_name="compliance_deletion_tool", permissions=compliance_tool_permissions)
The patient-facing app’s credential can never delete a single memory even if it were somehow tricked or exploited into trying, since its role simply doesn’t grant that action at all, while the compliance tool’s narrower, purpose-built role can fulfill a genuine right-to-erasure request without ever needing broader standing access to the rest of the platform. This is exactly the value role-based access control delivers for a use case like telehealth, where the consequences of a mistake or a compromised credential are severe enough that no single component should ever carry more capability than its actual job requires.
Role-based access control complements scoping by restricting not just which data a request can reach, but which kinds of operations a given credential should ever be trusted to perform at all. Both of these safeguards ultimately come down to when, exactly, in a memory system’s actual flow of operations they get checked and enforced. Our next chapter, When is scope enforced at write time vs query time?, takes up exactly that timing.