Agent mode·Plain-text view for agents and LLMsraw md →

The three tiers of platform permissions

System, Project, and Team — what each tier owns, where each enforces, and why this is the permission model regulated platforms keep landing on.

Jun 24, 2025 · 6 min read · Ayşe Yıldız, Customer Engineering · Engineering

Tags: #permissions · #rbac · #compliance · #platform


When platform teams talk about role-based access control, the conversation usually starts as "admin and viewer" and ends as "we need seventeen custom roles for the auditors." There is a better stopping point in the middle, and once a platform settles on it, the rest of the problems get easier.

This is the three-tier model Apinizer uses across every component — Manager, Worker, AI Gateway, Portal, APIops. It is not new. It is deliberate.

The three tiers

System. The platform itself. License, infrastructure, identity sources, cluster connections, environment provisioning. Touching this tier changes the platform's shape.

Project. A logical unit of ownership. A bank's Payments domain. A ministry's Citizen Services group. An insurer's Claims platform. A Project owns API surfaces, AI routes, environments, and the people inside it.

Team. People doing the work — developers, operators, reviewers, owners — inside a Project. Most day-to-day actions in the platform fire at this tier.

Every action in Apinizer flows through one of these tiers. The same check runs in the Manager UI, the APIops apply, the Portal subscription review, and the AI Gateway route change.

Why three is the right number

We landed here after watching enough customers fail at two and at seventeen.

Two tiers fail because Project is missing. When you only have "system admin" and "user," every team ends up with platform-level permissions or filing a ticket for everything. Either choice burns the auditor's trust.

Seventeen tiers fail because they're not enforced. Custom roles proliferate when nobody wants to admit the model is wrong, but the enforcement code only checks a few of them. You end up with a security policy and a security reality that don't match.

Three tiers map to how regulated platforms actually work:

  • The bank has a platform team (System) who provisions environments.
  • The Payments domain (Project) has its own people, its own APIs, its own audit trail.
  • Inside Payments, the engineering team (Team) does day-to-day work.

That's the org chart. The permission model just mirrors it.

What each tier owns

System

  • License, edition, feature flags
  • Identity sources (LDAP, AD, SAML, OAuth2 providers)
  • Environment provisioning (Kubernetes namespaces, cluster connections)
  • Cross-Project audit and reporting access
  • The four built-in roles themselves

System actions are rare and high-stakes. A typical platform with hundreds of API consumers has a handful of System operators. Their actions are the ones the regulator wants the cleanest audit trail for.

Project

  • API surfaces — REST, SOAP, gRPC, GraphQL, WebSocket
  • AI routes, MCP servers, A2A registrations
  • Environments allocated to the Project
  • Per-Project Gateway Path (the URL prefix exposed externally)
  • The four built-in roles, scoped to this Project: Owner, Manager, Developer, Viewer

A Project is the audit and ownership boundary. The audit trail for "Payments" answers the question "what happened in Payments" without needing platform-wide queries. The permission check for "can Ayşe deploy this proxy" only needs to know what Project the proxy lives in and what role Ayşe has there.

Team

  • Day-to-day work on the APIs, routes, and policies inside a Project
  • Subscription approvals on the Portal side
  • Reviews on APIops applies (when the project requires them)
  • Local observability — dashboards, alarms, audit slices

Most actions in a healthy platform happen at this tier. The blast radius is bounded to the Project. The audit captures who did what and when.

How enforcement actually works

The model is only useful if every code path enforces it. Apinizer's permission check is server-side, not UI-side. The Manager UI hides buttons users can't use, but the backend enforces the check on every request whether the button was hidden or not.

Inside the Manager, every Repository call passes through a permission aspect before persistence:

HTTP request → permission check → repository call → audit aspect → persistence

The permission check resolves the actor's identity (from the JWT or session), maps it to a Project and a role, and consults the action's required tier. If the actor doesn't have the right role at the right tier, the call returns 403 — and the audit aspect captures the denial.

That last part matters. A denied request is still audited. Auditors care about attempted actions, not just successful ones. The same trail that shows what was changed also shows what was tried and refused.

Crossing tiers

The interesting cases are the ones that cross tiers — actions where the actor is in one Project but the effect lands in another, or where a System operator needs to grant a Project something it can't grant itself.

Environment allocation. A System operator allocates an Environment to a Project. The Project's Owner then decides which Team roles can deploy to it. Neither side can self-grant.

Cross-Project audit access. A System role can query the audit trail across all Projects. Project Owners can only see their own. This keeps the regulator's auditor unbounded while keeping Payments people out of Claims and vice versa.

Portal subscription approval. A consumer in Project A subscribes to an API in Project B. The Owner of Project B approves or rejects. Project A's people don't get to approve their own subscription.

These rules sound obvious. They're load-bearing. Without them, a single compromised role compromises the platform.

Why this matches what the regulator wants

Banking, government, defense, and healthcare auditors keep coming back to the same three questions:

  1. Who can do what? The three-tier model answers this declaratively. Open the Project, list the roles, list the actions each role allows.
  2. Who did what and when? Every action — including denials — passes through the audit aspect. The trail is one Elasticsearch query away.
  3. Can someone get around the check? No, because the check is server-side, not UI-side. The framework refuses to fire the action if the permission aspect can't evaluate the request.

A bank running Apinizer with this model has answered the regulator's questions before the regulator asks. The trail is there. The roles are documented. The denials are audited. The framework itself enforces.

What this means for your team

If you're building or evaluating a platform and your permission model is "admin and user," you have a year of pain ahead of you. The first custom role someone asks for breaks the model. The fifth custom role breaks the enforcement. By role ten, no one knows who can do what.

If you're already in that swamp, three tiers is the way out — not because three is magical, but because it maps to how your organization actually works. Platform team. Domain teams. People inside domain teams. That's already your structure. The permission model should look like it.

If you want to see how this lands on a real platform — including the audit trail, the denial logging, and the APIops applies that respect the tiers — the team can walk you through it on your own cluster.


All posts · Book a Demo · Read the docs

© 2026 Apinizer. All rights reserved.