Roles & access control¶
Venturi's access model is built so an enterprise security review can find what it is looking for: least privilege, separation of duties, and a fail-closed default, all explainable on demand. Access is role-based at its core, with an attribute overlay for residency, data classification, and environment, and every grant is scoped to a position in your org-chart hierarchy. Nothing is reachable except through an explicit, scoped, auditable grant — and every access decision fails closed.
Target-state — enforcement hardening in progress
The canonical role model, the access-explain surface, and the fail-closed
contract described here are the committed design. Full runtime enforcement
of IdP-federated SSO/SCIM/MFA step-up, record-level tenant isolation
(the 403 TENANT_MISMATCH rejection), and the break-glass approval gate
are Target-state controls being wired against the canonical identity model
— not yet general. Rely on the binding labels in
Docs authority & product state
before treating any of these as GA.
This page covers the roles you assign, how scope and attributes narrow them, separation of duties, and how to keep access right over time. You assign and review all of it from the admin console; you can also drive it from your IdP through group mapping and SCIM. For the at-a-glance grid of every role's permissions, explicit exclusions, scope, and ABAC constraints, see the role & permission matrix.
The four canonical roles¶
| Role | What it can do | Typical count |
|---|---|---|
| Admin | Full access: user management, policy configuration, integration setup, pricing catalog, the intervention lifecycle, and enabling active interception. Can inspect full candidate sets, conflict classes, override history, and time-view divergence. | 1–3 |
| FinOps | Full access to cost data, chargeback exports, budget configuration, forecasting, and adoption reports; read access to attribution. Inspects ownership-vs-allocation distinctions and unresolved/unknown-spend reports. Cannot modify technical policies. | 2–10 |
| Engineer | Read access to attribution, team-scoped dashboards, and model analytics. Can propose interventions and overrides (which require a separate approval). Inspects service/project conflict explanations, routing divergence, and model lineage within scope. Cannot modify policies or pricing. | 10–100+ |
| Workforce-Data | The executive/people role (CTO / CHRO / Chief People Officer). Access to cohort-level adoption-intelligence and shadow-AI views by team, function, role, and tenure. Read-only with respect to attribution and policies. | 1–5 |
Workforce-Data is cohort-only by design
Individual-level workforce views are never a UI toggle. They are gated per tenant behind written legal sign-off plus a DPA amendment, are off in the EU regardless of role, and are always subject to the k=5 minimum-cohort suppression rule — any cohort smaller than five is rolled up to its parent, never shown. No custom role can weaken this.
A common shorthand is Viewer for the lowest-privilege, read-only access (for example, an executive reader, or a just-in-time-provisioned account before an admin elevates it) and Auditor for a time-boxed, read-only grant with evidence and audit-log access. Both are expressed as scoped grants in the model below, and both appear as rows in the role & permission matrix.
Scope: a grant is relative to a place¶
A role only means something at a scope node in the containment tree. The same "Engineer" role is very different at the tenant root than at one team:
| Scope level | What a grant there bounds |
|---|---|
| Organization | Contract, billing visibility, residency lane, domain claims |
| Tenant | The isolation boundary — all data, the tenant's encryption key, the audit trail |
| Workspace | A bounded analytic estate, e.g. a business unit or division |
| Team | The org-chart unit that owns cost and adoption |
| Project | The work unit attribution rolls up to |
| Object | A single saved view, export, dashboard, override set, budget policy, or connector |
Grants inherit downward: a FinOps @ Workspace: BU-West grant applies to
every team and project beneath BU-West, unless an object-level rule narrows it.
The admin console renders the effective scope path of
every grant — for example Engineer @ Workspace:BU-West (inherited) → Team:Payments
(effective) — so you can see why a user has access, not only that they do.
Attributes: narrowing a role further¶
On top of the role and scope, a grant carries attribute conditions that must all hold for access to be allowed. This is what lets one role behave correctly across residency lanes and data classes:
| Attribute | Example values | Effect | If it doesn't match |
|---|---|---|---|
residency |
us, eu, lane |
The subject's lane must match the resource's lane | Denied (residency is fail-closed) |
data_classification |
standard, restricted, individual-level-workforce |
individual-level-workforce requires the legal gate |
Denied; EU-hard-disabled regardless of role |
cohort |
cohort id / size | k=5 suppression applies to cohort reads | Suppressed (rolled to parent, not errored) |
env |
prod, staging, dev |
Scopes a grant to an environment | Denied (a dev grant can't read prod) |
A user's effective permission is the intersection of role, scope, inherited grants, attribute conditions, object-level sharing, and any active delegation.
Explain access¶
Because the model has several layers, the admin console can compute and explain the effective permission set for any user at any scope node — the resolved intersection, with each contributing factor itemized. When the answer is "deny," it tells you which factor decided:
An explained denial
A FinOps user with residency=eu asks for an Exports object classified
restricted in the us lane. "Explain access" returns:
Deny — residency mismatch: subject
eu≠ resourceus.
The preview always matches the live runtime decision, so what you see in the console is exactly what the user would experience. Denials a user hits are rendered the same way — with the determining factor named — never as a generic error or an outage banner.
Custom roles¶
A Tenant Admin can compose a custom role as a named permission set when the four canonical roles aren't a precise fit. The authoring UI is bounded by a ceiling:
- It hard-prevents selecting any permission your plan doesn't include or that would escalate past Admin.
- It shows a live diff against the nearest canonical role so you can see exactly what you're adding or removing.
- A saved custom role can never resolve to a grant exceeding the plan ceiling, and never weakens the Workforce-Data legal gate or k=5 suppression.
Step-up and separation of duties¶
Venturi enforces separation of duties (SoD) so no single person can both initiate and approve a consequential change, and surfaces the constraint before the action rather than failing at submit:
- The Engineer who proposes an attribution override cannot be its sole approver. When that same person opens the approval control, it is disabled with an explanation, and a separate principal must approve. Enforcement is server-side and fail-closed; the disabled UI control simply reflects it.
- The person who requests a support break-glass session cannot approve it.
A defined set of sensitive operations additionally requires a fresh step-up assertion (a WebAuthn or TOTP factor within a short freshness window), even inside a live session: enabling active interception, changing residency lane, creating or rotating API keys, changing a role binding, configuring the IdP or SCIM, creating an export, placing or releasing a legal hold, and approving break-glass.
Delegation and impersonation¶
For bounded, real-world needs, the admin console exposes two controlled patterns, both heavily instrumented:
- Delegation lets a user hand a subset of their grants to a colleague for a bounded window. The delegate, the delegated scope, and the expiry are shown, and the delegation auto-expires with no residual access.
- Impersonation ("view-as") lets an admin see Venturi as a lower-privileged user would. It requires step-up to begin, shows a persistent "viewing as <user>" banner, is read-only by default, records every action as an impersonated action in the audit log, and can never cross the tenant boundary.
Keep access right: recertification¶
Standing access drifts. The admin console measures and corrects it:
- Every grant shows its last-used time and an over-privilege flag when a role is broader than the user's actual usage.
- A recertification campaign asks grant owners to attest, downgrade, or revoke by a due date.
- A grant that is not attested by the due date is flagged stale, surfaced in the campaign report, and defaults to restricted (read-only) pending review — closure over preservation. Every attest, downgrade, and revoke writes an immutable audit entry.
The standing guarantees behind every grant
- Tenant isolation precedes every grant. A grant can only narrow within
the tenant; a cross-tenant request fails closed with
403 TENANT_MISMATCH. - Authorization fails closed. A missing, ambiguous, or denied permission blocks the operation — it never degrades into access.
- Every change is audited. Assigning, changing, delegating, recertifying, or revoking a grant writes an immutable audit entry.
Next steps¶
- Drive roles from your IdP via group mapping and SCIM.
- Manage users, policy, and recertification in the admin console.
- Verify enforcement and decisions in the audit log.