
Workspace-level permissions that carry down to every project and asset
A hierarchical access model in which permissions granted on a workspace or project apply to everything inside it, checked on every request.
- Partner
- A multinational advisory firm
- Period
- October 2024 to January 2026
- Access rules
- 6
- Direct, group, ownership, action rank, inheritance and parent read
- Hierarchy levels
- 4
- Workspace, project, asset and version
- Token types
- 3
- Entra ID, service-to-service and short-lived WebSocket
The challenge
Teams share some work and keep other work private. Assigning access asset by asset does not work when each project contains many pipelines, agents, dashboards and versions.
What we built
A Casbin policy model that follows the platform's resource hierarchy and is enforced on every route. Access can come from a direct grant, a group, ownership, a higher action or a parent resource, deny rules override allow rules, and every request is checked after the caller's identity is verified.
What was delivered
- Permissions inherited from workspace to project, asset and version
- Group-based access, ownership and deny rules
- A permission check on every route outside an allowlist, verified by a test
Partner background
Our partner is a multinational advisory firm whose teams work with large volumes of documents, spreadsheets, databases and email. It wanted one internal platform where those teams could build data pipelines and AI agents themselves, instead of commissioning a new application for each need. The platform had to run inside the partner's Microsoft 365 and Azure environment, keep each team's work separate, and move work from experiment to production through controlled environments. This case study covers one part of that platform; nine case studies describe the whole.
The challenge
Too many assets to manage one by one
Each project holds pipelines, agents, dashboards, endpoints and their versions. Granting access to each separately is slow and error-prone.
Exceptions
Sometimes one person must lose access to one asset inside a project they can otherwise see.
Different kinds of callers
Requests come from users in the browser, from other services and over long-lived WebSocket connections.
Navigation needs context
A user with access to one pipeline still needs to see the project and workspace that contain it.
Objectives
- Grant access once at the right level and have it apply below
- Support groups and ownership
- Rank actions so a broader permission covers a narrower one
- Let a deny rule override inherited access
- Verify every caller's identity before checking permissions
- Make it impossible to add a route without a permission check
Our role
CharCentric provided technical leadership and architecture within a multidisciplinary engineering team, and contributed directly to implementation. The platform was built over 16 months, from October 2024 to January 2026, as a Python and FastAPI backend on Azure.
Scope and timeline
The authorization model and token handling were built between March and July 2025.

Approach
Model the hierarchy explicitly
Resources are linked child to parent in the policy store: versions to assets, assets to projects, projects to workspaces. A policy on a parent applies to its children.
Rank actions
Actions are ordered, so a user allowed to manage a resource can also edit and read it.
Separate identity from permission
Middleware verifies identity first, through an HTTP or WebSocket strategy. The policy check then answers a single question: can this subject perform this action on this resource?
Implementation

Policy model
Requests are evaluated as subject, object and action against a reviewed Casbin model file. Rules cover direct access, group access, ownership, action ranking, inheritance from parent resources and reading a parent when a child is accessible. A deny rule overrides any allow.
Enforcement
A FastAPI dependency checks permission on every route except an explicit allowlist, such as health checks and sign-in. A test lists every route and fails if any other route has no check. Policy changes reach every API instance through a Casbin watcher.
Policy storage
Policies are stored in PostgreSQL through an asynchronous Casbin adapter.
Identity
Users authenticate with Microsoft Entra ID tokens. Services use machine-to-machine tokens. WebSocket connections use short-lived authorization tokens issued by the platform.

Tools and technologies
| Tool | Purpose |
|---|---|
| Casbin | Policy model and enforcement |
| PostgreSQL | Policy storage |
| Microsoft Entra ID | User identity |
| FastAPI middleware | Identity verification |
| SQLAlchemy | Asynchronous policy adapter |
What was delivered
- Access rules
- 6
- Hierarchy levels
- 4
- Token types
- 3
- Checked
- Every route
- A hierarchical permission model enforced on every route
- Group, ownership, action-rank and deny rules
- Identity verification for users, services and WebSockets
- Parent visibility for users with access to a child resource
Why it matters
Access control that matches how an organization actually groups its work is easier to administer and harder to get wrong. Modelling the hierarchy once replaces grants on every individual asset.
If your organization is planning a platform of this kind, or needs a specific part of one designed and delivered, we would be glad to discuss it.