Skip to content

Management API tokens + /api guard: foundation for a management CLI #1507

Open

Description

@helpcodeai

Summary

Add a management-scoped API credential and a guard that lets it authorize the
/api/* management endpoints, as the foundation for a full management CLI
(configure connectors, MCP servers, roles, users, SSO, code mode, settings,
memory/skills/knowledge-graph from the terminal — and by a connected agent).

This is a discussion-first issue per AGENTS.md (it changes authentication
and the Prisma schema). No code until the approach here is agreed.

Problem (verified in source)

There are two auth realms:

  • MCP realm — the MCP API key is authenticated by McpAuthMiddleware /
    McpCombinedAuthGuard, bound only to .forRoutes('mcp'), and resolves to a
    user pinned to one mcpServerId + mcpRoleId (a tool allow-list). It exists
    to call tools.
  • Management realm — every /api/* controller is guarded by
    AuthGuard('jwt') (browser session cookie) + @Roles('ADMIN') on sensitive
    routes. The MCP key cannot reach it, and cookie+CSRF is unusable from a CLI/CI.
    Cloud SSO users have no username/password login at all.

So a CLI cannot manage an instance today with the existing credential.

Proposal

Extend the existing API-key machinery rather than build a parallel system:

  1. Scope on the credential — add a scope to McpApiKey
    (mcp | management-read | management-admin). The key carries the user's
    identity and role; the scope is a downward cap, never an elevation.
    Effective power = min(user role, key scope). A non-admin's key still gets the
    same @Roles('ADMIN') 403s as in the dashboard.
  2. Guard — a guard that accepts a valid session JWT or a management
    key on /api/*, composing with the existing RolesGuard.
  3. Rate limiting — apply the existing per-principal rate-limit
    (mcp-principal-rate-limit.guard / mcp-rate-limit.middleware) to /api/*
    keyed to the management key, plus a per-key daily op cap. Protects against a
    looping tool/agent hammering the backend.
  4. Self-service minting — /api/mcp-keys is already JWT-only and
    user-scoped, so any user mints their own key; add the scope selector (offer
    only scopes <= the user's role). Agent-issued keys default to read-only.

Deployment behavior

Same feature on Cloud and self-hosted. Self-hosted gets it for free; on Cloud it
is the only non-interactive path for SSO users. No Cloud operator procedures are
part of this change.

Security

Least privilege (read vs admin scope), revocation, per-principal rate limit +
per-key quota, every management mutation already lands in the audit log, and
registration / forgot-password stay off the CLI (launcher-only to the web page,
no API call, no email).

Schema change + migration

New scope column (enum) on McpApiKey; migration included with the
implementation PR. Open to a separate ManagementApiKey table instead if we
prefer to keep MCP and management credentials fully distinct — a design question
for this thread.

Pre-work found

OpenAPI coverage audit: 179 / 207 management routes already carry
@ApiOperation. The gap is almost entirely File Search (file-search 3/23,
file-share 0/8, ~29 routes). Those two controllers need annotation before we
generate a typed CLI client from /api/docs.

Out of scope (follow-ups)

  • Browser OAuth login for human ergonomics / SSO (fast-follow; reuses the
    OAuth2 server already in the repo).
  • The CLI command surface itself (225 management commands mapped; one command
    per controller route) and public npm distribution.
  • Declarative apply / export ("instance as code").

Tasks

  • Agree credential shape (scope on McpApiKey vs separate table)
  • Define scope semantics (read = GET only; admin = all, role-capped)
  • Guard design (JWT-or-management-key) + tests
  • Apply per-principal rate limit + per-key quota to /api/*
  • Prisma migration
  • Mint UI + /api/mcp-keys scope selector (cap to role; agent default read-only)
  • Annotate File Search / file-share controllers for OpenAPI

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions