Admin Operations
Mandaitor includes admin-only endpoints for platform operations that are intentionally separate from tenant self-service APIs. These endpoints require a Cognito JWT whose principal belongs to the mandaitor-admins group. They should only be surfaced in internal operator dashboards.
Admin Endpoint Map
The following operations are implemented in the backend and included in the refreshed OpenAPI reference.
| Area | Endpoint | Purpose |
|---|---|---|
| Onboarding queue | GET /admin/onboarding | Lists beta or tenant access requests with optional status filtering and cursor pagination. |
| Onboarding review | POST /admin/onboarding/{requestId}/{action} | Approves or rejects an onboarding request. Supported actions are approve and reject. |
| Tenant detail | GET /admin/tenants/{id} | Returns tenant config, onboarding metadata, API key count, and mandate status counts. |
| Emergency response | POST /admin/tenants/{id}/kill-switch | Stops a tenant: disables its tools, stops its waiting executions and revokes its mandates. |
| System mode | GET /admin/system-mode | Reads the current platform operating mode. |
| System mode | POST /admin/system-mode | Changes the platform operating mode and affects API behavior globally. |
| Cognito proxy | POST /admin/auth/{action} | Proxies selected Cognito authentication actions from the browser. |
| Billing sync | POST /admin/billing/sync-customers | Backfills Stripe customers and optional metered subscriptions for active tenants. |
Tenant Detail Review
GET /admin/tenants/{id} is the operator-facing view for one tenant. It combines tenant configuration, linked onboarding request metadata, the number of API keys, and mandate status counts. The mandate statistics are designed for operational triage, so the implementation caps the sampled mandate set rather than acting as a long-term analytical warehouse.
GET /admin/tenants/tnt_ABC123
Authorization: Bearer <admin-cognito-jwt>
Admin dashboards should use this endpoint before executing irreversible operations such as the kill switch, because it gives the operator context about tenant state and active mandate footprint.
Emergency Kill Switch
POST /admin/tenants/{id}/kill-switch stops everything a tenant's agents may do. It is intended for security incidents, compliance breaches, or contract termination procedures. The request body carries a mandatory reason, recorded on the switch and in every audit event it causes.
Before it answers 202, it disables every tool the tenant has enabled. From then on no execution is created (403 TOOL_NOT_ENABLED), approved or written, and the MCP server lists no tool.
Then a worker finishes the job, in this order:
- It disables any tool still enabled: one enabled since, or all of them if the first attempt failed.
- It stops the tenant's executions that wait for an approval or for their write. Each ends
DENIEDwithstate_reasonKILL_SWITCH. Its approval leaves the approver's pending list, and what it reserved against a mandate's cumulative limits is given back. An execution already dispatched (EXECUTINGorUNKNOWN) finishes as it is: a write already sent cannot be recalled. One whose recheck had just passed is stopped by a last look at its tool, immediately before its dispatch is recorded. - It revokes every
ACTIVE,SUSPENDEDandPENDING_APPROVALmandate, each with a signedMANDATE_REVOKEDaudit event. A mandate pending approval can no longer be approved.
While the switch runs, POST /decisions authorizes nothing: what would have been ALLOW is DENY with code: KILL_SWITCH. An authorization given before the switch was requested is refused at its redemption with 409 KILL_SWITCH. See Decisions.
The 202 carries an execution_id and a status_path. Read GET /admin/tenants/{id}/kill-switch/{executionId} until its status is COMPLETED or FAILED; GET /admin/tenants/{id}/kill-switch lists the recent ones. The record shows its phase (TOOLS, EXECUTIONS, MANDATES), the tools it disabled in tools_disabled, and its counts:
| Field | Counts |
|---|---|
executions_cancelled | Executions stopped before they were written. |
executions_in_flight | Executions already dispatched, left to finish. |
executions_busy | Executions another step was deciding when the worker reached them. Each is refused, its tool disabled, unless its write was already under way. |
executions_failed | Executions whose stop could not be recorded on the audit trail. Each is refused the same way. |
revoked_count, skipped_count, failed_count | Mandates revoked; mandates that needed nothing; mandates whose revocation failed. |
A FAILED execution keeps the counts it reached. Requesting the switch again starts a new one, which picks up whatever is still enabled, waiting or active.
The emergency kill switch is irreversible for the affected mandates. Operators should require explicit confirmation in the UI and record the incident context before invoking it.
Afterwards, the tools stay disabled until the tenant enables each again (PUT /tenants/{id}/tools/{toolId}, or the dashboard's Connectors page). The record's tools_disabled lists them, in every environment, each with the environment and connector to enable it on again. Revoked mandates are not restored: the tenant creates new ones. The switch does not revoke API keys or end agent sessions, and proofs of mandate already issued remain valid until they expire. Revoke keys and suspend agents separately when the incident calls for it.
| Required UI safeguard | Rationale |
|---|---|
| Typed tenant ID confirmation | Reduces accidental execution against the wrong tenant. |
| Incident reason field | Preserves operator context for the audit trail. |
| Final confirmation dialog | Separates review from execution for an irreversible action. |
System Mode
The system mode endpoints allow operators to read and change global operating mode. Current modes include growth, sustain, maintenance, and frozen. Because this affects platform behavior across tenants, dashboard access should be restricted to trusted operators.
const mode = await adminClient.get("/admin/system-mode");
await adminClient.post("/admin/system-mode", {
mode: "maintenance",
reason: "Scheduled database migration",
});
Admin Auth Proxy
POST /admin/auth/{action} proxies selected Cognito operations for the admin browser application. This exists to handle browser-side Cognito identity-provider connectivity constraints while keeping authentication behavior centralized in the backend.
The dashboard should treat this endpoint as an authentication transport and should not expose it as a general tenant API. Only documented admin authentication actions should be sent to the proxy.
Billing Synchronization
POST /admin/billing/sync-customers is a migration and maintenance endpoint that scans active tenants and creates Stripe customer records where missing. When the backend is configured with a metered price ID, it can also create metered subscriptions.
This operation is useful after enabling billing for an existing tenant base. It should be run deliberately by platform administrators and monitored for provider-side failures.