Maker-checker — one person requests, a different person approves — is standard in banking and in any system where a single actor's mistake or malice is expensive. It applies directly to AI platform administration, where a single configuration change can widen what every agent in an organization can do.
The control is conceptually trivial and consistently implemented incorrectly, almost always in the same way: the approval check verifies that the approver has an administrative role, and the requester also has that role.
The Word "Administrator" Is the Bug
In a single-tenant system, "administrator" is unambiguous. In a multi-tenant platform it is not, and this is where self-approval reappears.
An organization owner is an administrator — of their organization. A platform staff member is an administrator — of the platform. If a review or approval endpoint checks for "an admin role," and an organization owner satisfies that check, then a customer can approve their own privileged actions.
Concrete instances of this failure:
- A marketplace listing review endpoint that accepts any admin, letting a publisher approve their own listing. See publishing agents to a marketplace.
- A dispute resolution endpoint that a counterparty's own owner can call. See agent task marketplaces and escrow.
- A scope-widening approval that the requesting team's lead can grant.
- A plan or quota override that an organization owner can apply to themselves.
The fix is structural: platform-staff authority must be a distinct role that no customer organization can hold, checked by a guard distinct from organization-role checks, and applied per route rather than inherited from a controller-level default. Administrative controllers accumulate routes with mixed authority requirements over time, and a class-level guard set once during initial implementation stops matching the routes added later.
Then, separately, a conflict-of-interest check: even a platform staff member must not approve an action concerning their own organization or an action they requested. Privilege and conflict are two different checks and both are needed.
Where It Belongs
Apply it asymmetrically. Friction should track the direction of risk, not the sensitivity of the resource.
Two approvers required:
- Widening a connection's scope, adding a connection to a new destination.
- Disabling or weakening a guardrail.
- Raising a spend ceiling or a rate limit.
- Lowering an approval threshold, or removing an approval requirement.
- Reducing audit retention or disabling audit writing. This is the highest-sensitivity change in the system, because it removes the evidence of everything else.
- Granting a role that can itself grant roles.
- Financial adjustments, escrow releases, refunds outside the normal path.
- Marketplace listing approval and dispute resolution.
- Cross-organization trust changes — adding a federation partner.
- Tenant data access outside the break-glass path.
Single actor sufficient:
- Narrowing scope, disabling a connection, lowering a ceiling.
- Adding or strengthening a guardrail.
- Killing an agent or revoking credentials.
- Raising an approval threshold.
The asymmetry is the design. Every action in the second list reduces what the system can do, so the worst case is a broken workflow — visible, quickly reversible, and far cheaper than the delay of finding an approver during an incident. See break-glass access for AI operations.
Making It Usable
Maker-checker fails in practice for a predictable reason: it becomes slow, so people work around it or approve reflexively.
Keep the two-approver set small. If approvals catch fifty items a day, approval becomes rubber-stamping within two weeks. Be disciplined about what genuinely needs two people. A control applied to too much protects nothing.
Show the diff, not the request. An approver needs to see exactly what changes: which scopes are added, what the ceiling moves from and to, which rule is being disabled. "Approve configuration change for agent X" is unreviewable and will be approved without thought.
Show the consequence where you can compute it. For scope changes, which calls would newly be permitted. For guardrail changes, evaluated against recorded traffic, what would newly pass. This turns approval from a trust exercise into a review. See staged guardrail rollout and shadow mode.
Notify the right people, in the channel they use. A request that sits in a queue nobody watches is a blocked workflow with no owner. See Slack and multi-channel alerting.
Expire pending requests. A request unapproved after a defined window closes rather than lingering, so the state is either applied or clearly not.
Record the reason on both sides. Why it was requested and why it was approved. The approver's reason is the more valuable of the two and the one usually omitted.
Never let the requester be the approver, even with two accounts. Bind the check to the person, not to the session — and watch for the shared-account pattern that defeats it entirely.
Approval Fatigue Is the Real Failure Mode
The mechanism can be perfectly implemented and still provide nothing if approvers stop reading.
Fatigue is a function of volume and reviewability. Reduce volume by narrowing what requires two approvers and by automating the checks that a human adds nothing to — signature verification, schema validation, policy linting. Improve reviewability by showing diffs and computed consequences rather than request titles.
Measure it. Approval latency dropping toward zero, approval rate at 100%, and approvals arriving seconds after the request are all signs that review has become a formality. Those are metrics worth watching on the approval system itself, and they are usually the earliest indication that the control has quietly stopped working.
Common questions
Is maker-checker overkill for a small team?
For a three-person team where everyone has full access, formal maker-checker is theatre. What is not overkill even at that size is recording every privileged change with actor and diff, and having a review habit — reading the change log weekly. As the team grows past the point where everyone knows every change, the approval requirement becomes worth its friction, and the record you have been keeping makes introducing it straightforward.
How does this work when an agent requests the change?
Treat the agent as the maker and require a human checker, always. An agent proposing a scope widening for itself is exactly the request that needs a human, and an agent must never be the approver — an approving agent is an injection away from approving anything. Record both the agent and the human principal that directed it.
What about changes needed at 3am during an incident?
Tightening needs no approval — that is the whole point of the asymmetry, and it covers nearly every legitimate 3am need. If a loosening is genuinely required, allow it as a time-limited grant with automatic reversion and mandatory retrospective review, rather than as a permanent change with a waived approval. The distinction preserves the control while not blocking the response.
How do I prevent role escalation from bypassing this?
The ability to grant roles must itself require two approvers, and no role should be able to grant a role broader than itself. Without that, a single actor grants themselves the approver role and self-approval returns through a different door. Test it: attempt to escalate your own role in a staging environment and confirm it fails. See RBAC and custom roles for AI operations.
How Praesidia approaches administrative governance
Praesidia keeps platform-staff authority separate from organization roles, so a customer organization owner cannot satisfy a platform-administration check — marketplace listing review and dispute resolution are reserved to platform staff, and a publisher cannot approve their own listing. Authority is evaluated per operation rather than inherited from a broad default.
Sensitive changes in the privilege-increasing direction can require a second approver while tightening, disabling, and killing remain immediate and ungated, and every change is versioned with a single-step rollback path. All administrative actions are written to the tamper-evident audit trail with the actor, the before-and-after state, and the recorded reason. See platform admin console and the Praesidia documentation.