How We're Building Unified Governance Engine
How Rox built unified, multi-source governance for users and AI agents using a single abstraction - the Pod with provenance, hierarchy rollups, and real-time sync.
The Problem:
What can a User or Agent (on behalf of the user) see and do within Rox and Why?
When a sales rep in US-East opens an account that belongs to US-West, something has gone wrong. When an AI agent surfaces a contact's private notes to the wrong manager, trust erodes instantly. There are many such scenarios which are the direct result of unifying the data from various sources without unifying their governance policies.
Rox builds a knowledge graph that connects data from a customer's CRM, data warehouse, calendar, email, and other operational systems into a single context layer. This is what makes our agents so capable but it also introduces a downstream challenge of not exposing this single context layer to just anyone in the organization.
If this problem statement is simple enough to understand, I assure you that building it is not.
Why Is This Hard to Solve?
What we're aiming to solve here is multi-source governance which is fundamentally different from the single system access control:
Source policies are bespoke and constantly changing: Large enterprises have deeply customized permissioning setups -- hierarchical territories, role-based visibility rollups, team-based sharing, org-wide defaults -- all defined in their source systems. These configurations change regularly as teams restructure, territories shift, and reps move between roles. A governance layer that ingests this data must stay in sync continuously, not just a one-time setup during onboarding.
Onboarding is gradual, not atomic. Customers don't flip a switch and connect every data source on day one. They start with Salesforce, add the warehouse a month later, bring in email after that. The governance system must work correctly at every stage of this progression -- enforcing whatever policies are available from the sources that are connected, without requiring the full picture to function.
Provenance must be traceable. When a user can see a record, the system must be able to answer why. Not just "you have access" but the full path: which team membership, which hierarchy rollup, which sharing rule, which source system contributed each piece of the access chain. Without this, admins can't audit, can't debug, and can't trust the system. This is the problem of access provenance — given a user U accessing an entity E originating from data source D, trace the complete set of reasons that access was granted.
We love that this is hard to solve which means this will push the envelope of what is possible especially if this leads to an increase in trust and adoption of Rox due to our vision.
The Vision
Our vision is solving this problem across every connected source, for every user and agent, in real time. This is the Unified Governance Graph which sits in between the Agent Interface and the Unified Knowledge Graph.

How We Are Solving It Technically
A single primitive: the Pod
The most complex part of any enterprise permissioning system isn't the access check itself — it's the proliferation of concepts that admins have to learn and maintain. Salesforce alone requires managing Roles, Territories (v1 and v2), Public Groups, Queues, Account Teams, Opportunity Teams, and Manual Shares. Each concept has its own hierarchy, its own membership model, and its own rules for how access propagates. Debugging why a rep can see a record means tracing through all of them.
We replaced all of these with a single abstraction: the Pod.
A Pod is a group of security entities (users, service accounts, or agents) that can be assigned access to records. Pods have members with roles (owner, member) and optional permission sets scoped to their membership. They can be organized into hierarchies. They can expire. That's it, and it turns out that's enough to model every access pattern enterprises need.
Territory management becomes creating Pods named
US-WestandUS-Central, arranging them under a parent PodAMER, and assigning records to each.Organization-wide defaults become a single Pod containing every user, with permissions set to public or private.
Team-based collaboration becomes a Pod with a few users and some shared records.
Time-limited access becomes a Pod with an expiration date.
But there's still one thing missing. To support hierarchical access roll-ups, because organizations and geographies are inherently hierarchical in nature; a Pod has another property: it can be linked to other Pods in a tree-based hierarchy, i.e., at most one parent and any number of children.
Insight: The insight is that all of these use cases share the same underlying structure: a group of people, a set of records, and a set of permissions connecting them. The differences are in how the hierarchy propagates access -- and we handle that with exactly two hierarchy types.
Just Two Hierarchy Types
Record-Based: Access flows upward through records. A user in a parent Pod can see all records assigned to child Pods, but not the other effective access of users in those child Pods. This is the right model for territories: a user in the
AMERPod should see accounts assigned toUS-WestandUS-East, but shouldn't automatically inherit everything the US-West reps can see through their personal shares. There's no limit on the number of record-based hierarchies — an organization can have separate hierarchies for geography, industry vertical, product line, and account tier simultaneously.User-Based: Access flows upward through people. A manager in an ancestor Pod inherits the effective access of every user in descendant Pods -- regardless of where that access originated. If a rep has access to a record through a team Pod, a sharing rule, or direct ownership, the manager sees it too. This models the Salesforce role hierarchy and manager-based reporting structures. We limit organizations to exactly one user-based hierarchy to prevent the combinatorial explosion that makes Salesforce permissioning difficult to reason about.
Why?: This separation eliminates an entire class of access leakage bugs. In systems that conflate user visibility with record assignment, promoting someone in a territory hierarchy accidentally grants them visibility into records they obtained through unrelated team memberships.

Three Pillars of Access
At the most fundamental level, we need to solve for three layers of access:
Object-level access: which determines whether a user can interact with a type of entity at all.
Can this user read Accounts? Create Opportunities? Delete Contacts? These permissions are defined in Permission Sets — bundles of object and field permissions assigned to users either directly or through Pod membership.
We support two types:
Standard Permission Sets (pre-built for common personas like Sales Rep or Sales Manager)
Custom Permission Sets (additive, for fine-grained adjustments). Across all assigned permission sets, the most permissive grant wins.
Field-level access: which controls visibility at the column level within an object.
Even if a user can read Accounts, they might not be able to see the
annual_revenuefield. This is standard in enterprise CRMs.Where we go further is record-level field restrictions: the ability to redact a specific field on a specific record. In Salesforce, if you can see a field on one Account, you see it on all Accounts.
Our system allows restricting field visibility per-record, scoped to specific Pods or permission sets. A field like
deal_amountmight be visible on most opportunities but redacted on a particularly sensitive deal, shown only to members of the executive Pod.
Record-level access: which is where Pods do the heavy lifting.
A user's effective access to a specific record is the union of six sources: direct ownership, external access (for example: synced from Salesforce, Dynamics, etc.), Pod record assignments, sharing rule grants, record hierarchy rollups, and user hierarchy rollups.
The most permissive access level across all sources wins. We then intersect this with the object and field permissions — you can't edit a record if your permission set doesn't grant edit on that object type, even if the Pod gives you full access.
The effective access formula:
Translating external access models
Building our own permissioning model is necessary but not sufficient. Customers already have deeply configured access policies in their existing CRMs -- sometimes years of accumulated sharing rules, territory assignments, and role hierarchies. We can't ask them to recreate all of that in Rox. Instead, we ingest the raw permissioning metadata from Salesforce and translate it into our Pod model.
The translation works in three stages:
First, we sync the raw Salesforce permission tables: role hierarchies, territory hierarchies, share tables (
AccountShare,OpportunityShare, etc.), group memberships, permission sets, and org-wide defaults - into staging tables via periodic API sync. These tables are stored with minimal transformation, preserving the original Salesforce IDs for traceability.Second, a translation layer maps each Salesforce concept to its Pod equivalent. The Salesforce role hierarchy becomes a user-based Pod hierarchy. Territory hierarchies become record-based Pod hierarchies. Public groups become flat Pods. Account and opportunity teams become Pods with record-scoped access. Sharing rules become criteria-based grants targeting Pods. Permission sets map directly. Throughout, we preserve provenance metadata — i.e., every translated Pod carries its
source_system,source_type, andsource_idso we can always trace it back.Third, once translated, these CRM-sourced Pods coexist with Rox-native Pods in the same unified model. The access resolution engine doesn't distinguish between them. A user might have access to a record through a Salesforce role hierarchy Pod, a Rox-native territory Pod, and a time-limited collaboration Pod simultaneously -- the engine unions all paths and the most permissive wins.

Access provenance: tracing the "Why"
The most common support question in any enterprise permissioning system is not "does this user have access?"; it's "why does this user have access?" or "why doesn't this user have access?" Without provenance, admins are left clicking through configuration screens trying to reconstruct the access path manually. But we're uniquely positioned to solve this problem because we're unifying all the data sources. Every access decision in our system produces a provenance record - a structured trace of every source that contributed to the final result. When a user accesses a record, the provenance captures each contributing Pod membership, each sharing rule that matched, each hierarchy rollup that propagated access, and the source system each originated from. The effective access level is computed as the most permissive across all paths, but the individual paths are preserved.
This enables two views that admins care about most:
User-Record Trail: answers "how is this specific user able to access this specific record?". It shows every Pod, sharing rule, and hierarchy path that connects them.
Record-Access View: answers "who can access this record and through which paths?". It shows every user and Pod with access and the source of each grant. Both views work across data sources. If a user has access through a Salesforce role hierarchy Pod and a Rox-native team Pod and a sharing rule, all three paths appear in the trace with their original source attribution.
Access provenance: tracing the "why"
The most common support question in any enterprise permissioning system is not "does this user have access?"; it's "why does this user have access?" or "why doesn't this user have access?" Without provenance, admins are left clicking through configuration screens trying to reconstruct the access path manually.
We're uniquely positioned to solve this because the governance layer already unifies access from every connected source. Every access decision produces a provenance record: a structured trace of every source that contributed to the final result. When a user accesses a record, the provenance captures each contributing Pod membership, each sharing rule that matched, each hierarchy rollup that propagated access, and the source system each originated from. The effective access level is the most permissive across all paths, but the individual paths are preserved.
This enables two views that admins care about most:
User-record trail: answers "how is this specific user able to access this specific record?", showing every Pod, sharing rule, and hierarchy path that connects them.
Record-access view: answers "who can access this record and through which paths?", showing every user and Pod with access and the source of each grant.
Both views work across data sources. If a user has access through a Salesforce role hierarchy Pod, a Rox-native team Pod, and a sharing rule, all three paths appear in the trace with their original source attribution. This is the difference between a permissioning system that enforces access and one that explains it.
Future Work
There is a lot of ground still to cover. Access provenance: the ability to trace exactly why a user or agent can access a specific record across every data source, is next. So are deny rules, approval-based sharing workflows, automatic permission set translation from non-Salesforce CRMs like HubSpot and Dynamics 365, and governance policies that extend natively into data lakes and warehouses. The long-term vision is a single governance layer that enforces access across every system an enterprise connects to Rox, viz., CRM, warehouse, lake, email, calendar, with a complete audit trail for every decision.
If building unified governance for AI agents at enterprise scale sounds like your kind of problem, we're hiring.
Last updated

